Skip to content

Commit 452cd4c

Browse files
authored
feat: add solutions to lc problem: No.1876 (doocs#3594)
1 parent 3bda3f4 commit 452cd4c

File tree

8 files changed

+284
-76
lines changed

8 files changed

+284
-76
lines changed

solution/1800-1899/1876.Substrings of Size Three with Distinct Characters/README.md

+101-25
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,17 @@ tags:
6464

6565
<!-- solution:start -->
6666

67-
### 方法一
67+
### 方法一:滑动窗口
68+
69+
我们可以维护一个滑动窗口,使得窗口内的字符不重复。初始时,我们用一个长度为 $26$ 的二进制整数 $\textit{mask}$ 表示窗口内的字符,其中第 $i$ 位为 $1$ 表示字符 $i$ 在窗口内出现过,否则表示字符 $i$ 在窗口内没有出现过。
70+
71+
然后,我们遍历字符串 $s$,对于每一个位置 $r$,如果 $\textit{s}[r]$ 在窗口内出现过,我们需要将窗口的左边界 $l$ 右移,直到窗口内不再有重复的字符。在这之后,我们将 $\textit{s}[r]$ 加入窗口内,此时如果窗口的长度大于等于 $3$,那么我们就找到了一个以 $\textit{s}[r]$ 结尾的长度为 $3$ 的好子字符串。
72+
73+
遍历结束后,我们就找到了所有的好子字符串的数量。
74+
75+
时间复杂度 $O(n)$,其中 $n$ 为字符串 $s$ 的长度。空间复杂度 $O(1)$。
76+
77+
> 该解法可以拓展到长度为 $k$ 的好子字符串的数量。
6878
6979
<!-- tabs:start -->
7080

@@ -73,44 +83,97 @@ tags:
7383
```python
7484
class Solution:
7585
def countGoodSubstrings(self, s: str) -> int:
76-
count, n = 0, len(s)
77-
for i in range(n - 2):
78-
count += s[i] != s[i + 1] and s[i] != s[i + 2] and s[i + 1] != s[i + 2]
79-
return count
86+
ans = mask = l = 0
87+
for r, x in enumerate(map(lambda c: ord(c) - 97, s)):
88+
while mask >> x & 1:
89+
y = ord(s[l]) - 97
90+
mask ^= 1 << y
91+
l += 1
92+
mask |= 1 << x
93+
ans += int(r - l + 1 >= 3)
94+
return ans
8095
```
8196

8297
#### Java
8398

8499
```java
85100
class Solution {
86101
public int countGoodSubstrings(String s) {
87-
int count = 0, n = s.length();
88-
for (int i = 0; i < n - 2; ++i) {
89-
char a = s.charAt(i), b = s.charAt(i + 1), c = s.charAt(i + 2);
90-
if (a != b && a != c && b != c) {
91-
++count;
102+
int ans = 0;
103+
int n = s.length();
104+
for (int l = 0, r = 0, mask = 0; r < n; ++r) {
105+
int x = s.charAt(r) - 'a';
106+
while ((mask >> x & 1) == 1) {
107+
int y = s.charAt(l++) - 'a';
108+
mask ^= 1 << y;
92109
}
110+
mask |= 1 << x;
111+
ans += r - l + 1 >= 3 ? 1 : 0;
93112
}
94-
return count;
113+
return ans;
95114
}
96115
}
97116
```
98117

118+
#### C++
119+
120+
```cpp
121+
class Solution {
122+
public:
123+
int countGoodSubstrings(string s) {
124+
int ans = 0;
125+
int n = s.length();
126+
for (int l = 0, r = 0, mask = 0; r < n; ++r) {
127+
int x = s[r] - 'a';
128+
while ((mask >> x & 1) == 1) {
129+
int y = s[l++] - 'a';
130+
mask ^= 1 << y;
131+
}
132+
mask |= 1 << x;
133+
ans += r - l + 1 >= 3 ? 1 : 0;
134+
}
135+
return ans;
136+
}
137+
};
138+
```
139+
140+
#### Go
141+
142+
```go
143+
func countGoodSubstrings(s string) (ans int) {
144+
mask, l := 0, 0
145+
for r, c := range s {
146+
x := int(c - 'a')
147+
for (mask>>x)&1 == 1 {
148+
y := int(s[l] - 'a')
149+
l++
150+
mask ^= 1 << y
151+
}
152+
mask |= 1 << x
153+
if r-l+1 >= 3 {
154+
ans++
155+
}
156+
}
157+
return
158+
}
159+
```
160+
99161
#### TypeScript
100162

101163
```ts
102164
function countGoodSubstrings(s: string): number {
103-
const n: number = s.length;
104-
let count: number = 0;
105-
for (let i: number = 0; i < n - 2; ++i) {
106-
let a: string = s.charAt(i),
107-
b: string = s.charAt(i + 1),
108-
c: string = s.charAt(i + 2);
109-
if (a != b && a != c && b != c) {
110-
++count;
165+
let ans = 0;
166+
const n = s.length;
167+
for (let l = 0, r = 0, mask = 0; r < n; ++r) {
168+
const x = s.charCodeAt(r) - 'a'.charCodeAt(0);
169+
while ((mask >> x) & 1) {
170+
const y = s.charCodeAt(l++) - 'a'.charCodeAt(0);
171+
mask ^= 1 << y;
111172
}
173+
mask |= 1 << x;
174+
ans += r - l + 1 >= 3 ? 1 : 0;
112175
}
113-
return count;
176+
return ans;
114177
}
115178
```
116179

@@ -123,13 +186,26 @@ class Solution {
123186
* @return Integer
124187
*/
125188
function countGoodSubstrings($s) {
126-
$cnt = 0;
127-
for ($i = 0; $i < strlen($s) - 2; $i++) {
128-
if ($s[$i] != $s[$i + 1] && $s[$i] != $s[$i + 2] && $s[$i + 1] != $s[$i + 2]) {
129-
$cnt++;
189+
$ans = 0;
190+
$n = strlen($s);
191+
$l = 0;
192+
$r = 0;
193+
$mask = 0;
194+
195+
while ($r < $n) {
196+
$x = ord($s[$r]) - ord('a');
197+
while (($mask >> $x) & 1) {
198+
$y = ord($s[$l++]) - ord('a');
199+
$mask ^= 1 << $y;
130200
}
201+
$mask |= 1 << $x;
202+
if ($r - $l + 1 >= 3) {
203+
$ans++;
204+
}
205+
$r++;
131206
}
132-
return $cnt++;
207+
208+
return $ans;
133209
}
134210
}
135211
```

solution/1800-1899/1876.Substrings of Size Three with Distinct Characters/README_EN.md

+102-26
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ tags:
3535
<pre>
3636
<strong>Input:</strong> s = &quot;xyzzaz&quot;
3737
<strong>Output:</strong> 1
38-
<strong>Explanation:</strong> There are 4 substrings of size 3: &quot;xyz&quot;, &quot;yzz&quot;, &quot;zza&quot;, and &quot;zaz&quot;.
38+
<strong>Explanation:</strong> There are 4 substrings of size 3: &quot;xyz&quot;, &quot;yzz&quot;, &quot;zza&quot;, and &quot;zaz&quot;.
3939
The only good substring of length 3 is &quot;xyz&quot;.
4040
</pre>
4141

@@ -62,7 +62,17 @@ The good substrings are &quot;abc&quot;, &quot;bca&quot;, &quot;cab&quot;, and &
6262

6363
<!-- solution:start -->
6464

65-
### Solution 1
65+
### Solution 1: Sliding Window
66+
67+
We can maintain a sliding window such that the characters within the window are not repeated. Initially, we use a binary integer $\textit{mask}$ of length $26$ to represent the characters within the window, where the $i$-th bit being $1$ indicates that character $i$ has appeared in the window, otherwise it indicates that character $i$ has not appeared in the window.
68+
69+
Then, we traverse the string $s$. For each position $r$, if $\textit{s}[r]$ has appeared in the window, we need to move the left boundary $l$ of the window to the right until there are no repeated characters in the window. After this, we add $\textit{s}[r]$ to the window. At this point, if the length of the window is greater than or equal to $3$, then we have found a good substring of length $3$ ending at $\textit{s}[r]$.
70+
71+
After the traversal, we have found the number of all good substrings.
72+
73+
The time complexity is $O(n)$, where $n$ is the length of the string $s$. The space complexity is $O(1)$.
74+
75+
> This solution can be extended to find the number of good substrings of length $k$.
6676
6777
<!-- tabs:start -->
6878

@@ -71,44 +81,97 @@ The good substrings are &quot;abc&quot;, &quot;bca&quot;, &quot;cab&quot;, and &
7181
```python
7282
class Solution:
7383
def countGoodSubstrings(self, s: str) -> int:
74-
count, n = 0, len(s)
75-
for i in range(n - 2):
76-
count += s[i] != s[i + 1] and s[i] != s[i + 2] and s[i + 1] != s[i + 2]
77-
return count
84+
ans = mask = l = 0
85+
for r, x in enumerate(map(lambda c: ord(c) - 97, s)):
86+
while mask >> x & 1:
87+
y = ord(s[l]) - 97
88+
mask ^= 1 << y
89+
l += 1
90+
mask |= 1 << x
91+
ans += int(r - l + 1 >= 3)
92+
return ans
7893
```
7994

8095
#### Java
8196

8297
```java
8398
class Solution {
8499
public int countGoodSubstrings(String s) {
85-
int count = 0, n = s.length();
86-
for (int i = 0; i < n - 2; ++i) {
87-
char a = s.charAt(i), b = s.charAt(i + 1), c = s.charAt(i + 2);
88-
if (a != b && a != c && b != c) {
89-
++count;
100+
int ans = 0;
101+
int n = s.length();
102+
for (int l = 0, r = 0, mask = 0; r < n; ++r) {
103+
int x = s.charAt(r) - 'a';
104+
while ((mask >> x & 1) == 1) {
105+
int y = s.charAt(l++) - 'a';
106+
mask ^= 1 << y;
90107
}
108+
mask |= 1 << x;
109+
ans += r - l + 1 >= 3 ? 1 : 0;
91110
}
92-
return count;
111+
return ans;
93112
}
94113
}
95114
```
96115

116+
#### C++
117+
118+
```cpp
119+
class Solution {
120+
public:
121+
int countGoodSubstrings(string s) {
122+
int ans = 0;
123+
int n = s.length();
124+
for (int l = 0, r = 0, mask = 0; r < n; ++r) {
125+
int x = s[r] - 'a';
126+
while ((mask >> x & 1) == 1) {
127+
int y = s[l++] - 'a';
128+
mask ^= 1 << y;
129+
}
130+
mask |= 1 << x;
131+
ans += r - l + 1 >= 3 ? 1 : 0;
132+
}
133+
return ans;
134+
}
135+
};
136+
```
137+
138+
#### Go
139+
140+
```go
141+
func countGoodSubstrings(s string) (ans int) {
142+
mask, l := 0, 0
143+
for r, c := range s {
144+
x := int(c - 'a')
145+
for (mask>>x)&1 == 1 {
146+
y := int(s[l] - 'a')
147+
l++
148+
mask ^= 1 << y
149+
}
150+
mask |= 1 << x
151+
if r-l+1 >= 3 {
152+
ans++
153+
}
154+
}
155+
return
156+
}
157+
```
158+
97159
#### TypeScript
98160

99161
```ts
100162
function countGoodSubstrings(s: string): number {
101-
const n: number = s.length;
102-
let count: number = 0;
103-
for (let i: number = 0; i < n - 2; ++i) {
104-
let a: string = s.charAt(i),
105-
b: string = s.charAt(i + 1),
106-
c: string = s.charAt(i + 2);
107-
if (a != b && a != c && b != c) {
108-
++count;
163+
let ans = 0;
164+
const n = s.length;
165+
for (let l = 0, r = 0, mask = 0; r < n; ++r) {
166+
const x = s.charCodeAt(r) - 'a'.charCodeAt(0);
167+
while ((mask >> x) & 1) {
168+
const y = s.charCodeAt(l++) - 'a'.charCodeAt(0);
169+
mask ^= 1 << y;
109170
}
171+
mask |= 1 << x;
172+
ans += r - l + 1 >= 3 ? 1 : 0;
110173
}
111-
return count;
174+
return ans;
112175
}
113176
```
114177

@@ -121,13 +184,26 @@ class Solution {
121184
* @return Integer
122185
*/
123186
function countGoodSubstrings($s) {
124-
$cnt = 0;
125-
for ($i = 0; $i < strlen($s) - 2; $i++) {
126-
if ($s[$i] != $s[$i + 1] && $s[$i] != $s[$i + 2] && $s[$i + 1] != $s[$i + 2]) {
127-
$cnt++;
187+
$ans = 0;
188+
$n = strlen($s);
189+
$l = 0;
190+
$r = 0;
191+
$mask = 0;
192+
193+
while ($r < $n) {
194+
$x = ord($s[$r]) - ord('a');
195+
while (($mask >> $x) & 1) {
196+
$y = ord($s[$l++]) - ord('a');
197+
$mask ^= 1 << $y;
128198
}
199+
$mask |= 1 << $x;
200+
if ($r - $l + 1 >= 3) {
201+
$ans++;
202+
}
203+
$r++;
129204
}
130-
return $cnt++;
205+
206+
return $ans;
131207
}
132208
}
133209
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
class Solution {
2+
public:
3+
int countGoodSubstrings(string s) {
4+
int ans = 0;
5+
int n = s.length();
6+
for (int l = 0, r = 0, mask = 0; r < n; ++r) {
7+
int x = s[r] - 'a';
8+
while ((mask >> x & 1) == 1) {
9+
int y = s[l++] - 'a';
10+
mask ^= 1 << y;
11+
}
12+
mask |= 1 << x;
13+
ans += r - l + 1 >= 3 ? 1 : 0;
14+
}
15+
return ans;
16+
}
17+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
func countGoodSubstrings(s string) (ans int) {
2+
mask, l := 0, 0
3+
for r, c := range s {
4+
x := int(c - 'a')
5+
for (mask>>x)&1 == 1 {
6+
y := int(s[l] - 'a')
7+
l++
8+
mask ^= 1 << y
9+
}
10+
mask |= 1 << x
11+
if r-l+1 >= 3 {
12+
ans++
13+
}
14+
}
15+
return
16+
}

0 commit comments

Comments
 (0)