Skip to content

Commit 208bba0

Browse files
committed
feat: add solutions to lc problem: No.2067
No.2067.Number of Equal Count Substrings
1 parent 2c5ec48 commit 208bba0

File tree

7 files changed

+361
-347
lines changed

7 files changed

+361
-347
lines changed

solution/2000-2099/2067.Number of Equal Count Substrings/README.md

+126-117
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,13 @@
6161

6262
<!-- 这里可写通用的实现逻辑 -->
6363

64-
前缀和统计每个位置各个字母出现的次数。然后根据 count 枚举子字符串左右端点,check 是否满足条件,是则 ans 加 1。
64+
**方法一:枚举 + 滑动窗口**
6565

66-
最后返回 ans。
66+
我们可以在 $[1..26]$ 范围内枚举子串的字母种类数 $x$,那么子串长度就是 $count \times x$。
67+
68+
接下来,我们将当前子串长度作为窗口的大小,统计窗口大小中有多少种字母的个数为 $count$,记录在 $y$ 中。如果此时 $x = y$,说明当前窗口中的字母个数都为 $count$,那么就可以将答案加一。
69+
70+
时间复杂度 $O(n \times C)$,空间复杂度 $O(C)$。其中 $n$ 为字符串 $s$ 的长度,而 $C$ 为字母的种类数,本题中 $C = 26$。
6771

6872
<!-- tabs:start -->
6973

@@ -74,34 +78,23 @@
7478
```python
7579
class Solution:
7680
def equalCountSubstrings(self, s: str, count: int) -> int:
77-
n = len(s)
78-
if count > n:
79-
return 0
80-
counter = [[0] * 26 for _ in range(n + 1)]
81-
82-
def check(i, j):
83-
c1 = counter[i]
84-
c2 = counter[j + 1]
85-
for k in range(26):
86-
if c2[k] == 0 or c1[k] == c2[k]:
87-
continue
88-
if c2[k] - c1[k] != count:
89-
return False
90-
return True
91-
9281
ans = 0
93-
for i, c in enumerate(s):
94-
idx = ord(c) - ord('a')
95-
for j in range(26):
96-
counter[i + 1][j] = counter[i][j]
97-
counter[i + 1][idx] = counter[i][idx] + 1
98-
l = 0
99-
for _ in range(26):
100-
l += count
101-
j = i - l + 1
102-
if j < 0:
103-
break
104-
ans += check(j, i)
82+
for x in range(1, 27):
83+
m = count * x
84+
if m > len(s):
85+
break
86+
cnt = Counter()
87+
y = 0
88+
for i, c in enumerate(s):
89+
cnt[c] += 1
90+
y += cnt[c] == count
91+
y -= cnt[c] == count + 1
92+
j = i - m
93+
if j >= 0:
94+
cnt[s[j]] -= 1
95+
y += cnt[s[j]] == count
96+
y -= cnt[s[j]] == count - 1
97+
ans += x == y
10598
return ans
10699
```
107100

@@ -112,44 +105,39 @@ class Solution:
112105
```java
113106
class Solution {
114107
public int equalCountSubstrings(String s, int count) {
115-
int n = s.length();
116-
if (count > n) {
117-
return 0;
118-
}
119-
int[][] counter = new int[n + 1][26];
120108
int ans = 0;
121-
for (int i = 0; i < n; ++i) {
122-
int idx = s.charAt(i) - 'a';
123-
for (int j = 0; j < 26; ++j) {
124-
counter[i + 1][j] = counter[i][j];
125-
}
126-
counter[i + 1][idx] = counter[i][idx] + 1;
127-
int l = 0;
128-
for (int k = 0; k < 26; ++k) {
129-
l += count;
130-
int j = i - l + 1;
131-
if (j < 0) {
132-
break;
109+
int n = s.length();
110+
for (int x = 1; x < 27 && count * x <= n; ++x) {
111+
int m = count * x;
112+
int[] cnt = new int[26];
113+
int y = 0;
114+
for (int i = 0; i < n; ++i) {
115+
int a = s.charAt(i) - 'a';
116+
++cnt[a];
117+
if (cnt[a] == count) {
118+
++y;
119+
}
120+
if (cnt[a] == count + 1) {
121+
--y;
122+
}
123+
int j = i - m;
124+
if (j >= 0) {
125+
int b = s.charAt(j) - 'a';
126+
--cnt[b];
127+
if (cnt[b] == count) {
128+
++y;
129+
}
130+
if (cnt[b] == count - 1) {
131+
--y;
132+
}
133+
}
134+
if (x == y) {
135+
++ans;
133136
}
134-
ans += check(j, i, count, counter) ? 1 : 0;
135137
}
136138
}
137139
return ans;
138140
}
139-
140-
private boolean check(int i, int j, int count, int[][] counter) {
141-
int[] c1 = counter[i];
142-
int[] c2 = counter[j + 1];
143-
for (int k = 0; k < 26; ++k) {
144-
if (c2[k] == 0 || c1[k] == c2[k]) {
145-
continue;
146-
}
147-
if (c2[k] - c1[k] != count) {
148-
return false;
149-
}
150-
}
151-
return true;
152-
}
153141
}
154142
```
155143

@@ -159,84 +147,105 @@ class Solution {
159147
class Solution {
160148
public:
161149
int equalCountSubstrings(string s, int count) {
162-
int n = s.size();
163-
if (count > n) return 0;
164-
vector<vector<int>> counter(n + 1, vector<int>(26));
165150
int ans = 0;
166-
for (int i = 0; i < n; ++i) {
167-
int idx = s[i] - 'a';
168-
for (int j = 0; j < 26; ++j) counter[i + 1][j] = counter[i][j];
169-
counter[i + 1][idx] = counter[i][idx] + 1;
170-
int l = 0;
171-
for (int k = 0; k < 26; ++k) {
172-
l += count;
173-
int j = i - l + 1;
174-
if (j < 0) break;
175-
ans += check(j, i, count, counter);
151+
int n = s.size();
152+
int cnt[26];
153+
for (int x = 1; x < 27 && count * x <= n; ++x) {
154+
int m = count * x;
155+
memset(cnt, 0, sizeof cnt);
156+
int y = 0;
157+
for (int i = 0; i < n; ++i) {
158+
int a = s[i] - 'a';
159+
++cnt[a];
160+
y += cnt[a] == count;
161+
y -= cnt[a] == count + 1;
162+
int j = i - m;
163+
if (j >= 0) {
164+
int b = s[j] - 'a';
165+
--cnt[b];
166+
y += cnt[b] == count;
167+
y -= cnt[b] == count - 1;
168+
}
169+
ans += x == y;
176170
}
177171
}
178172
return ans;
179173
}
180-
181-
bool check(int i, int j, int count, vector<vector<int>>& counter) {
182-
auto& c1 = counter[i];
183-
auto& c2 = counter[j + 1];
184-
for (int k = 0; k < 26; ++k) {
185-
if (c2[k] == 0 || c1[k] == c2[k]) continue;
186-
if (c2[k] - c1[k] != count) return false;
187-
}
188-
return true;
189-
}
190174
};
191175
```
192176
193177
### **Go**
194178
195179
```go
196-
func equalCountSubstrings(s string, count int) int {
180+
func equalCountSubstrings(s string, count int) (ans int) {
197181
n := len(s)
198-
if count > n {
199-
return 0
200-
}
201-
counter := make([][]int, n+1)
202-
for i := range counter {
203-
counter[i] = make([]int, 26)
204-
}
205-
ans := 0
206-
check := func(i, j int) bool {
207-
c1, c2 := counter[i], counter[j+1]
208-
for k := 0; k < 26; k++ {
209-
if c2[k] == 0 || c1[k] == c2[k] {
210-
continue
182+
for x := 1; x < 27 && x*count <= n; x++ {
183+
m := x * count
184+
y := 0
185+
cnt := [26]int{}
186+
for i, c := range s {
187+
a := c - 'a'
188+
cnt[a]++
189+
if cnt[a] == count {
190+
y++
211191
}
212-
if c2[k]-c1[k] != count {
213-
return false
192+
if cnt[a] == count+1 {
193+
y--
214194
}
215-
}
216-
return true
217-
}
218-
for i, c := range s {
219-
idx := c - 'a'
220-
for j := 0; j < 26; j++ {
221-
counter[i+1][j] = counter[i][j]
222-
}
223-
counter[i+1][idx] = counter[i][idx] + 1
224-
l := 0
225-
for k := 0; k < 26; k++ {
226-
l += count
227-
j := i - l + 1
228-
if j < 0 {
229-
break
195+
j := i - m
196+
if j >= 0 {
197+
b := s[j] - 'a'
198+
cnt[b]--
199+
if cnt[b] == count {
200+
y++
201+
}
202+
if cnt[b] == count-1 {
203+
y--
204+
}
230205
}
231-
if check(j, i) {
206+
if x == y {
232207
ans++
233208
}
234209
}
235210
}
236-
return ans
211+
return
237212
}
238213
```
239214

215+
### **JavaScript**
216+
217+
```js
218+
/**
219+
* @param {string} s
220+
* @param {number} count
221+
* @return {number}
222+
*/
223+
var equalCountSubstrings = function (s, count) {
224+
let ans = 0;
225+
const n = s.length;
226+
for (let x = 1; x <= 26 && x * count <= n; ++x) {
227+
const m = x * count;
228+
const cnt = new Array(26).fill(0);
229+
let y = 0;
230+
for (let i = 0; i < n; ++i) {
231+
const a = s.charCodeAt(i) - 'a'.charCodeAt(0);
232+
++cnt[a];
233+
y += cnt[a] == count;
234+
y -= cnt[a] == count + 1;
235+
const j = i - m;
236+
if (j >= 0) {
237+
const b = s.charCodeAt(j) - 'a'.charCodeAt(0);
238+
--cnt[b];
239+
y += cnt[b] == count;
240+
y -= cnt[b] == count - 1;
241+
}
242+
ans += x == y;
243+
}
244+
}
245+
return ans;
246+
};
247+
```
248+
240249
### **...**
241250

242251
```

0 commit comments

Comments
 (0)