Skip to content

Commit 095d4db

Browse files
committed
add new problems
1 parent 573739c commit 095d4db

6 files changed

+232
-8
lines changed

Algorithms Basics/Chapter 1. Array_String/28. Implement strStr().cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ public int StrStr(string haystack, string needle) {
1010
int m = haystack.Length, n = needle.Length;
1111
if (n == 0) return 0;
1212
if (m < n) return -1;
13-
for (int i = 0; i < m - n; i++) {
13+
for (int i = 0; i < m - n + 1; i++) {
1414
int j = 0;
1515
for (j = 0; j < n; j++) {
1616
if (haystack[i + j] != needle[j])

CodeClearWar/151. Reverse Words in a String.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,18 @@ public class Solution {
77
public string ReverseWords(string s) {
88
if (s == null || s.Length == 0) return "";
99
int j = s.Length;
10-
var str = new StringBuilder();
10+
var reversed = new StringBuilder();
1111
for (int i = s.Length - 1; i >= 0; i--) {
1212
if (s[i] == ' ') {
1313
j = i;
1414
} else if (i == 0 || s[i - 1] == ' ') {
15-
if (str.Length != 0) {
16-
str.Append(' ');
15+
if (reversed.Length != 0) {
16+
reversed.Append(' ');
1717
}
18-
str.Append(s.Substring(i, j - i));
18+
reversed.Append(s.Substring(i, j - i));
1919
}
2020
}
21-
return str.ToString();
21+
return reversed.ToString();
2222
}
2323
}
2424

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
The trick is to maintain a sliding window that always satisfies the invariant where there
3+
are always at most two distinct characters in it. When we add a new character that breaks
4+
this invariant, how can we move the begin pointer to satisfy the invariant?
5+
6+
we can use a dictionary to save times for each char, and use a counter to save the num of distinct.
7+
8+
when moving the right pointer, we increase the appear times, also increase the counts of distinct char
9+
when meet new char;
10+
when moving the left pointer, we decrease the appear times, and decrease the counts if the appear times = 0;
11+
12+
O(n) run time, O(n) space.
13+
*/
14+
15+
public class Solution {
16+
public int LengthOfLongestSubstringTwoDistinct(string s) {
17+
int maxLen = 0;
18+
if (s == null || s.Length == 0) return maxLen;
19+
var dict = new Dictionary<char, int>();
20+
int i = 0, numDistinct = 0;
21+
for (int j = 0; j < s.Length; j++) {
22+
if (!dict.ContainsKey(s[j]) || dict[s[j]] == 0) {
23+
dict[s[j]] = 1;
24+
numDistinct++;
25+
} else {
26+
dict[s[j]] += 1;
27+
}
28+
while (numDistinct > 2) {
29+
dict[s[i]] -= 1;
30+
if (dict[s[i]] == 0) numDistinct--;
31+
i++;
32+
}
33+
maxLen = Math.Max(maxLen, j - i + 1);
34+
}
35+
return maxLen;
36+
}
37+
}
38+
39+
/*
40+
Similar Questions
41+
Longest Substring Without Repeating Characters
42+
Sliding Window Maximum
43+
Longest Substring with At Most K Distinct Characters
44+
45+
*/
46+
47+
/*
48+
if string only contains ascii, then we can use int[256] to save as O(1) space.
49+
*/
50+
51+
public class Solution {
52+
public int LengthOfLongestSubstringTwoDistinct(string s) {
53+
int maxLen = 0;
54+
if (s == null || s.Length == 0) return maxLen;
55+
var dict = new int[256];
56+
int i = 0, numDistinct = 0;
57+
for (int j = 0; j < s.Length; j++) {
58+
if (dict[s[j]] == 0) numDistinct++;
59+
dict[s[j]]++;
60+
while (numDistinct > 2) {
61+
dict[s[i]]--;
62+
if (dict[s[i]] == 0) numDistinct--;
63+
i++;
64+
}
65+
maxLen = Math.Max(maxLen, j - i + 1);
66+
}
67+
return maxLen;
68+
}
69+
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*
2+
Solution tip:
3+
use two start pointer (slower) l = 0, (faster) r = 0.
4+
use a dictionary to save (char,index). use ans to save maxLen.
5+
if s[r] is not found in the dictionary, then ans = Math.Max(ans, r - l + 1);
6+
if s[r] is found in dictonary, then then l should shift to the new index,
7+
if dict[s[r]] > l, shift to dict[s[r]] + 1; then ans = Math.Max(ans, r - l + 1);
8+
9+
O(n) runtime, O(n) space – Single iteration:
10+
*/
11+
12+
public class Solution {
13+
public int LengthOfLongestSubstring(string s) {
14+
if (s == null || s.Length == 0) return 0;
15+
int ans = 0;
16+
int l = 0;
17+
var dict = new Dictionary<char, int>();
18+
for (int r = 0; r < s.Length; r++) {
19+
var cur = s[r];
20+
if (dict.ContainsKey(cur)) {
21+
l = Math.Max(l, dict[cur] + 1);
22+
}
23+
dict[cur] = r;
24+
ans = Math.Max(ans, r - l + 1);
25+
}
26+
return ans;
27+
}
28+
}
29+
/*
30+
Next challenges: Longest Substring with At Most Two Distinct Characters
31+
*/
32+
33+
/*
34+
if string only contains ascii. then we can use O(1) space.
35+
use a int[] charmap = new int[256], instead of dictionary.
36+
*/
37+
public class Solution {
38+
public int LengthOfLongestSubstring(string s) {
39+
int[] charMap = new int[256];
40+
Arrays.fill(charMap, -1);
41+
int i = 0, maxLen = 0;
42+
for (int j = 0; j < s.Length; j++) {
43+
if (charMap[s[j]] >= i) {
44+
i = charMap[s[j]] + 1;
45+
}
46+
charMap[s[j]] = j;
47+
maxLen = Math.Max(j - i + 1, maxLen);
48+
}
49+
return maxLen;
50+
}
51+
}
52+
/*
53+
By using HashSet as a sliding window, checking if a character in the current can be done in O(1).
54+
55+
A sliding window is an abstract concept commonly used in array/string problems. A window is a
56+
range of elements in the array/string which usually defined by the start and end indices,
57+
i.e. [i, j)(left-closed, right-open). A sliding window is a window "slides" its two
58+
boundaries to the certain direction. For example, if we slide [i, j) to the right by 1 element,
59+
then it becomes [i+1, j+1) (left-closed, right-open).
60+
61+
Back to our problem. We use HashSet to store the characters in current window [i, j) (j = i initially).
62+
Then we slide the index j to the right. If it is not in the HashSet, we slide j further. Doing so
63+
until s[j] is already in the HashSet. At this point, we found the maximum size of substrings
64+
without duplicate characters start with index ii. If we do this for all i, we get our answer.
65+
66+
Complexity Analysis
67+
68+
Time complexity : O(2n) = O(n). In the worst case each character will be visited twice by i and j.
69+
70+
Space complexity : O(min(m, n)). Same as the previous approach. We need O(k) space for the
71+
sliding window, where k is the size of the Set. The size of the Set is upper bounded by the
72+
size of the string n and the size of the charset/alphabet m.
73+
*/
74+
75+
public class Solution {
76+
public int LengthOfLongestSubstring(string s) {
77+
int n = s.Length;
78+
var set = new HashSet<>();
79+
int ans = 0, i = 0, j = 0;
80+
while (i < n && j < n) {
81+
// try to extend the range [i, j]
82+
if (!set.Contains(s.[j])){
83+
set.Add(s[j++]));
84+
ans = Math.Max(ans, j - i);
85+
}
86+
else {
87+
set.Remove(s[i++]);
88+
}
89+
}
90+
return ans;
91+
}
92+
}

CodeClearWar/65. Valid Number.cs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
2+
/*
3+
Solution:
4+
This problem is very similar to Question [8. String to Integer (atoi)]. Due to many corner
5+
cases, it is helpful to break the problem down to several components that can be solved
6+
individually.
7+
A string could be divided into these four substrings in the order from left to right:
8+
s1. Leading whitespaces (optional).
9+
s2. Plus (+) or minus (–) sign (optional).
10+
s3. Number.
11+
s4. Optional trailing whitespaces (optional).
12+
13+
On the other hand, a decimal number could be further divided into three parts:
14+
a. Integer part
15+
b. Decimal point
16+
c. Fractional part
17+
18+
A number could contain an optional exponent part, which is marked by a character ‘e’
19+
followed by a whole number (exponent). For example, “1e10” is numeric. Modify the
20+
above code to adapt to this new requirement.
21+
22+
*/
23+
public class Solution {
24+
public bool IsNumber(string s) {
25+
int i = 0, n = s.Length;
26+
while (i < n && s[i] == ' ') i++;
27+
if (i < n && (s[i] == '+' || s[i] == '-')) i++;
28+
bool isNumeric = false;
29+
while (i < n && (s[i] >= '0' && s[i] <= '9')) {
30+
i++;
31+
isNumeric = true;
32+
}
33+
// decimal part
34+
if (i < n && s[i] == '.') {
35+
i++;
36+
while (i < n && (s[i] >= '0' && s[i] <= '9')) {
37+
i ++;
38+
isNumeric = true;
39+
}
40+
}
41+
// exponent part
42+
if (isNumeric && i < n && s[i] == 'e') {
43+
i++;
44+
isNumeric = false;
45+
if (i < n && (s[i] == '+' || s[i] == '-')) i++;
46+
while (i < n && (s[i] >= '0' && s[i] <= '9')) {
47+
i ++;
48+
isNumeric = true;
49+
}
50+
}
51+
while (i < n && s[i] == ' ') i++;
52+
return isNumeric && i == n;
53+
}
54+
}
55+
56+
/*
57+
Next challenges:
58+
Edit Distance
59+
Judge Route Circle
60+
Maximum Swap
61+
62+
*/

CodeClearWar/8. String to Integer (atoi).cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ public int MyAtoi(string str)
1313
{
1414
if (str == null) return 0;
1515
int i = 0, n = str.Length;
16-
while (i < n && char.IsWhiteSpace(str[i])) i++;
16+
// while (i < n && char.IsWhiteSpace(str[i])) i++;
17+
while (i < n && str[i] == ' ') i++;
1718
if (i == n) return 0;
1819
int sign = 1;
1920
if (i < n && str[i] == '+') {
@@ -23,7 +24,7 @@ public int MyAtoi(string str)
2324
i++;
2425
}
2526
int num = 0;
26-
while (i < n && char.IsDigit(str[i])) {
27+
while (i < n && char.IsDigit(str[i])) { // can use str[i] >= '0' and str[i] <= '9' to check IsDigit
2728
int digit = str[i] - '0';
2829
if (num > maxDiv10 || num == maxDiv10 && digit >= 8) {
2930
return sign == 1 ? int.MaxValue : int.MinValue;

0 commit comments

Comments
 (0)