Skip to content

Commit 2e04c0f

Browse files
authored
feat: add solutions to lc problem: No.3261 (#3717)
No.3261.Count Substrings That Satisfy K-Constraint II
1 parent e315eae commit 2e04c0f

File tree

21 files changed

+458
-30
lines changed

21 files changed

+458
-30
lines changed

lcof2/剑指 Offer II 119. 最长连续序列/README.md

+7-7
Original file line numberDiff line numberDiff line change
@@ -230,11 +230,11 @@ class Solution {
230230
if n < 2 {
231231
return n
232232
}
233-
233+
234234
let sortedNums = Array(Set(nums)).sorted()
235235
var ans = 1
236236
var currentStreak = 1
237-
237+
238238
for i in 1..<sortedNums.count {
239239
if sortedNums[i] == sortedNums[i - 1] + 1 {
240240
currentStreak += 1
@@ -243,7 +243,7 @@ class Solution {
243243
currentStreak = 1
244244
}
245245
}
246-
246+
247247
return ans
248248
}
249249
}
@@ -395,21 +395,21 @@ class Solution {
395395
func longestConsecutive(_ nums: [Int]) -> Int {
396396
let numSet: Set<Int> = Set(nums)
397397
var longestStreak = 0
398-
398+
399399
for num in nums {
400400
if !numSet.contains(num - 1) {
401401
var currentNum = num
402402
var currentStreak = 1
403-
403+
404404
while numSet.contains(currentNum + 1) {
405405
currentNum += 1
406406
currentStreak += 1
407407
}
408-
408+
409409
longestStreak = max(longestStreak, currentStreak)
410410
}
411411
}
412-
412+
413413
return longestStreak
414414
}
415415
}

solution/3200-3299/3258.Count Substrings That Satisfy K-Constraint I/README.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ tags:
8888

8989
我们用两个变量 $\textit{cnt0}$ 和 $\textit{cnt1}$ 分别记录当前窗口内的 $0$ 和 $1$ 的个数,用 $\textit{ans}$ 记录满足 $k$ 约束的子字符串的个数,用 $l$ 记录窗口的左边界。
9090

91-
当我们右移窗口时,如果窗口内的 $0$ 和 $1$ 的个数都大于 $k$,我们就需要左移窗口,直到窗口内的 $0$ 和 $1$ 的个数都不大于 $k$。此时,窗口内的所有子字符串都满足 $k$ 约束,个数为 $r - l + 1$,其中 $r$ 是窗口的右边界。我们将这个个数累加到 $\textit{ans}$ 中。
91+
当我们右移窗口时,如果窗口内的 $0$ 和 $1$ 的个数都大于 $k$,我们就需要左移窗口,直到窗口内的 $0$ 和 $1$ 的个数都不大于 $k$。此时,窗口内所有以 $r$ 作为右端点的子字符串都满足 $k$ 约束,个数为 $r - l + 1$,其中 $r$ 是窗口的右边界。我们将这个个数累加到 $\textit{ans}$ 中。
9292

9393
最后,我们返回 $\textit{ans}$ 即可。
9494

@@ -175,9 +175,9 @@ function countKConstraintSubstrings(s: string, k: number): number {
175175
const cnt: [number, number] = [0, 0];
176176
let [ans, l] = [0, 0];
177177
for (let r = 0; r < s.length; ++r) {
178-
cnt[s.charCodeAt(r) - 48]++;
178+
cnt[+s[r]]++;
179179
while (cnt[0] > k && cnt[1] > k) {
180-
cnt[s.charCodeAt(l++) - 48]--;
180+
cnt[+s[l++]]--;
181181
}
182182
ans += r - l + 1;
183183
}

solution/3200-3299/3258.Count Substrings That Satisfy K-Constraint I/README_EN.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -173,9 +173,9 @@ function countKConstraintSubstrings(s: string, k: number): number {
173173
const cnt: [number, number] = [0, 0];
174174
let [ans, l] = [0, 0];
175175
for (let r = 0; r < s.length; ++r) {
176-
cnt[s.charCodeAt(r) - 48]++;
176+
cnt[+s[r]]++;
177177
while (cnt[0] > k && cnt[1] > k) {
178-
cnt[s.charCodeAt(l++) - 48]--;
178+
cnt[+s[l++]]--;
179179
}
180180
ans += r - l + 1;
181181
}

solution/3200-3299/3258.Count Substrings That Satisfy K-Constraint I/Solution.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ function countKConstraintSubstrings(s: string, k: number): number {
22
const cnt: [number, number] = [0, 0];
33
let [ans, l] = [0, 0];
44
for (let r = 0; r < s.length; ++r) {
5-
cnt[s.charCodeAt(r) - 48]++;
5+
cnt[+s[r]]++;
66
while (cnt[0] > k && cnt[1] > k) {
7-
cnt[s.charCodeAt(l++) - 48]--;
7+
cnt[+s[l++]]--;
88
}
99
ans += r - l + 1;
1010
}

solution/3200-3299/3261.Count Substrings That Satisfy K-Constraint II/README.md

+137-4
Original file line numberDiff line numberDiff line change
@@ -81,32 +81,165 @@ tags:
8181

8282
<!-- solution:start -->
8383

84-
### 方法一
84+
### 方法一:滑动窗口 + 前缀和
85+
86+
我们用两个变量 $\textit{cnt0}$ 和 $\textit{cnt1}$ 分别记录当前窗口内的 $0$ 和 $1$ 的个数,指针 $i$ 和 $j$ 分别标识窗口的左右边界。用一个数组 $d$ 记录每个位置 $i$ 右边第一个不满足 $k$ 约束的位置,初始时 $d[i] = n$。另外,用一个长度为 $n + 1$ 的前缀和数组 $\textit{pre}[i]$ 记录以前 $i$ 个位置作为右边界的满足 $k$ 约束的子字符串的个数。
87+
88+
当我们右移窗口时,如果窗口内的 $0$ 和 $1$ 的个数都大于 $k$,我们将 $d[i]$ 更新为 $j$,表示位置 $i$ 右边第一个不满足 $k$ 约束的位置。然后我们将 $i$ 右移一位,直到窗口内的 $0$ 和 $1$ 的个数都不大于 $k$。此时,我们可以计算出以 $j$ 为右边界的满足 $k$ 约束的子字符串的个数,即 $j - i + 1$,我们更新到前缀和数组中。
89+
90+
最后,对于每个查询 $[l, r]$,我们首先找出 $l$ 右边第一个不满足 $k$ 约束的位置 $p$,那么 $p = \min(r + 1, d[l])$,那么 $[l, p - 1]$ 的所有子字符串都满足 $k$ 约束,个数为 $(1 + p - l) \times (p - l) / 2$,然后,我们计算以 $[p, r]$ 为右边界的满足 $k$ 约束的子字符串的个数,即 $\textit{pre}[r + 1] - \textit{pre}[p]$,最后将两者相加即可。
91+
92+
时间复杂度 $O(n + m)$,空间复杂度 $O(n)$。其中 $n$ 和 $m$ 分别为字符串 $s$ 的长度和查询数组 $\textit{queries}$ 的长度。
8593

8694
<!-- tabs:start -->
8795

8896
#### Python3
8997

9098
```python
91-
99+
class Solution:
100+
def countKConstraintSubstrings(
101+
self, s: str, k: int, queries: List[List[int]]
102+
) -> List[int]:
103+
cnt = [0, 0]
104+
i, n = 0, len(s)
105+
d = [n] * n
106+
pre = [0] * (n + 1)
107+
for j, x in enumerate(map(int, s)):
108+
cnt[x] += 1
109+
while cnt[0] > k and cnt[1] > k:
110+
d[i] = j
111+
cnt[int(s[i])] -= 1
112+
i += 1
113+
pre[j + 1] = pre[j] + j - i + 1
114+
ans = []
115+
for l, r in queries:
116+
p = min(r + 1, d[l])
117+
a = (1 + p - l) * (p - l) // 2
118+
b = pre[r + 1] - pre[p]
119+
ans.append(a + b)
120+
return ans
92121
```
93122

94123
#### Java
95124

96125
```java
97-
126+
class Solution {
127+
public long[] countKConstraintSubstrings(String s, int k, int[][] queries) {
128+
int[] cnt = new int[2];
129+
int n = s.length();
130+
int[] d = new int[n];
131+
Arrays.fill(d, n);
132+
long[] pre = new long[n + 1];
133+
for (int i = 0, j = 0; j < n; ++j) {
134+
cnt[s.charAt(j) - '0']++;
135+
while (cnt[0] > k && cnt[1] > k) {
136+
d[i] = j;
137+
cnt[s.charAt(i++) - '0']--;
138+
}
139+
pre[j + 1] = pre[j] + j - i + 1;
140+
}
141+
int m = queries.length;
142+
long[] ans = new long[m];
143+
for (int i = 0; i < m; ++i) {
144+
int l = queries[i][0], r = queries[i][1];
145+
int p = Math.min(r + 1, d[l]);
146+
long a = (1L + p - l) * (p - l) / 2;
147+
long b = pre[r + 1] - pre[p];
148+
ans[i] = a + b;
149+
}
150+
return ans;
151+
}
152+
}
98153
```
99154

100155
#### C++
101156

102157
```cpp
103-
158+
class Solution {
159+
public:
160+
vector<long long> countKConstraintSubstrings(string s, int k, vector<vector<int>>& queries) {
161+
int cnt[2]{};
162+
int n = s.size();
163+
vector<int> d(n, n);
164+
long long pre[n + 1];
165+
pre[0] = 0;
166+
for (int i = 0, j = 0; j < n; ++j) {
167+
cnt[s[j] - '0']++;
168+
while (cnt[0] > k && cnt[1] > k) {
169+
d[i] = j;
170+
cnt[s[i++] - '0']--;
171+
}
172+
pre[j + 1] = pre[j] + j - i + 1;
173+
}
174+
vector<long long> ans;
175+
for (const auto& q : queries) {
176+
int l = q[0], r = q[1];
177+
int p = min(r + 1, d[l]);
178+
long long a = (1LL + p - l) * (p - l) / 2;
179+
long long b = pre[r + 1] - pre[p];
180+
ans.push_back(a + b);
181+
}
182+
return ans;
183+
}
184+
};
104185
```
105186
106187
#### Go
107188
108189
```go
190+
func countKConstraintSubstrings(s string, k int, queries [][]int) (ans []int64) {
191+
cnt := [2]int{}
192+
n := len(s)
193+
d := make([]int, n)
194+
for i := range d {
195+
d[i] = n
196+
}
197+
pre := make([]int, n+1)
198+
for i, j := 0, 0; j < n; j++ {
199+
cnt[s[j]-'0']++
200+
for cnt[0] > k && cnt[1] > k {
201+
d[i] = j
202+
cnt[s[i]-'0']--
203+
i++
204+
}
205+
pre[j+1] = pre[j] + j - i + 1
206+
}
207+
for _, q := range queries {
208+
l, r := q[0], q[1]
209+
p := min(r+1, d[l])
210+
a := (1 + p - l) * (p - l) / 2
211+
b := pre[r+1] - pre[p]
212+
ans = append(ans, int64(a+b))
213+
}
214+
return
215+
}
216+
```
109217

218+
#### TypeScript
219+
220+
```ts
221+
function countKConstraintSubstrings(s: string, k: number, queries: number[][]): number[] {
222+
const cnt: [number, number] = [0, 0];
223+
const n = s.length;
224+
const d: number[] = Array(n).fill(n);
225+
const pre: number[] = Array(n + 1).fill(0);
226+
for (let i = 0, j = 0; j < n; ++j) {
227+
cnt[+s[j]]++;
228+
while (Math.min(cnt[0], cnt[1]) > k) {
229+
d[i] = j;
230+
cnt[+s[i++]]--;
231+
}
232+
pre[j + 1] = pre[j] + j - i + 1;
233+
}
234+
const ans: number[] = [];
235+
for (const [l, r] of queries) {
236+
const p = Math.min(r + 1, d[l]);
237+
const a = ((1 + p - l) * (p - l)) / 2;
238+
const b = pre[r + 1] - pre[p];
239+
ans.push(a + b);
240+
}
241+
return ans;
242+
}
110243
```
111244

112245
<!-- tabs:end -->

0 commit comments

Comments
 (0)