Skip to content

feat: add solutions to lc problem: No.3261 #3717

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions lcof2/剑指 Offer II 119. 最长连续序列/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,11 +230,11 @@ class Solution {
if n < 2 {
return n
}

let sortedNums = Array(Set(nums)).sorted()
var ans = 1
var currentStreak = 1

for i in 1..<sortedNums.count {
if sortedNums[i] == sortedNums[i - 1] + 1 {
currentStreak += 1
Expand All @@ -243,7 +243,7 @@ class Solution {
currentStreak = 1
}
}

return ans
}
}
Expand Down Expand Up @@ -395,21 +395,21 @@ class Solution {
func longestConsecutive(_ nums: [Int]) -> Int {
let numSet: Set<Int> = Set(nums)
var longestStreak = 0

for num in nums {
if !numSet.contains(num - 1) {
var currentNum = num
var currentStreak = 1

while numSet.contains(currentNum + 1) {
currentNum += 1
currentStreak += 1
}

longestStreak = max(longestStreak, currentStreak)
}
}

return longestStreak
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ tags:

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

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

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

Expand Down Expand Up @@ -175,9 +175,9 @@ function countKConstraintSubstrings(s: string, k: number): number {
const cnt: [number, number] = [0, 0];
let [ans, l] = [0, 0];
for (let r = 0; r < s.length; ++r) {
cnt[s.charCodeAt(r) - 48]++;
cnt[+s[r]]++;
while (cnt[0] > k && cnt[1] > k) {
cnt[s.charCodeAt(l++) - 48]--;
cnt[+s[l++]]--;
}
ans += r - l + 1;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,9 +173,9 @@ function countKConstraintSubstrings(s: string, k: number): number {
const cnt: [number, number] = [0, 0];
let [ans, l] = [0, 0];
for (let r = 0; r < s.length; ++r) {
cnt[s.charCodeAt(r) - 48]++;
cnt[+s[r]]++;
while (cnt[0] > k && cnt[1] > k) {
cnt[s.charCodeAt(l++) - 48]--;
cnt[+s[l++]]--;
}
ans += r - l + 1;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ function countKConstraintSubstrings(s: string, k: number): number {
const cnt: [number, number] = [0, 0];
let [ans, l] = [0, 0];
for (let r = 0; r < s.length; ++r) {
cnt[s.charCodeAt(r) - 48]++;
cnt[+s[r]]++;
while (cnt[0] > k && cnt[1] > k) {
cnt[s.charCodeAt(l++) - 48]--;
cnt[+s[l++]]--;
}
ans += r - l + 1;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,32 +81,165 @@ tags:

<!-- solution:start -->

### 方法一
### 方法一:滑动窗口 + 前缀和

我们用两个变量 $\textit{cnt0}$ 和 $\textit{cnt1}$ 分别记录当前窗口内的 $0$ 和 $1$ 的个数,指针 $i$ 和 $j$ 分别标识窗口的左右边界。用一个数组 $d$ 记录每个位置 $i$ 右边第一个不满足 $k$ 约束的位置,初始时 $d[i] = n$。另外,用一个长度为 $n + 1$ 的前缀和数组 $\textit{pre}[i]$ 记录以前 $i$ 个位置作为右边界的满足 $k$ 约束的子字符串的个数。

当我们右移窗口时,如果窗口内的 $0$ 和 $1$ 的个数都大于 $k$,我们将 $d[i]$ 更新为 $j$,表示位置 $i$ 右边第一个不满足 $k$ 约束的位置。然后我们将 $i$ 右移一位,直到窗口内的 $0$ 和 $1$ 的个数都不大于 $k$。此时,我们可以计算出以 $j$ 为右边界的满足 $k$ 约束的子字符串的个数,即 $j - i + 1$,我们更新到前缀和数组中。

最后,对于每个查询 $[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]$,最后将两者相加即可。

时间复杂度 $O(n + m)$,空间复杂度 $O(n)$。其中 $n$ 和 $m$ 分别为字符串 $s$ 的长度和查询数组 $\textit{queries}$ 的长度。

<!-- tabs:start -->

#### Python3

```python

class Solution:
def countKConstraintSubstrings(
self, s: str, k: int, queries: List[List[int]]
) -> List[int]:
cnt = [0, 0]
i, n = 0, len(s)
d = [n] * n
pre = [0] * (n + 1)
for j, x in enumerate(map(int, s)):
cnt[x] += 1
while cnt[0] > k and cnt[1] > k:
d[i] = j
cnt[int(s[i])] -= 1
i += 1
pre[j + 1] = pre[j] + j - i + 1
ans = []
for l, r in queries:
p = min(r + 1, d[l])
a = (1 + p - l) * (p - l) // 2
b = pre[r + 1] - pre[p]
ans.append(a + b)
return ans
```

#### Java

```java

class Solution {
public long[] countKConstraintSubstrings(String s, int k, int[][] queries) {
int[] cnt = new int[2];
int n = s.length();
int[] d = new int[n];
Arrays.fill(d, n);
long[] pre = new long[n + 1];
for (int i = 0, j = 0; j < n; ++j) {
cnt[s.charAt(j) - '0']++;
while (cnt[0] > k && cnt[1] > k) {
d[i] = j;
cnt[s.charAt(i++) - '0']--;
}
pre[j + 1] = pre[j] + j - i + 1;
}
int m = queries.length;
long[] ans = new long[m];
for (int i = 0; i < m; ++i) {
int l = queries[i][0], r = queries[i][1];
int p = Math.min(r + 1, d[l]);
long a = (1L + p - l) * (p - l) / 2;
long b = pre[r + 1] - pre[p];
ans[i] = a + b;
}
return ans;
}
}
```

#### C++

```cpp

class Solution {
public:
vector<long long> countKConstraintSubstrings(string s, int k, vector<vector<int>>& queries) {
int cnt[2]{};
int n = s.size();
vector<int> d(n, n);
long long pre[n + 1];
pre[0] = 0;
for (int i = 0, j = 0; j < n; ++j) {
cnt[s[j] - '0']++;
while (cnt[0] > k && cnt[1] > k) {
d[i] = j;
cnt[s[i++] - '0']--;
}
pre[j + 1] = pre[j] + j - i + 1;
}
vector<long long> ans;
for (const auto& q : queries) {
int l = q[0], r = q[1];
int p = min(r + 1, d[l]);
long long a = (1LL + p - l) * (p - l) / 2;
long long b = pre[r + 1] - pre[p];
ans.push_back(a + b);
}
return ans;
}
};
```

#### Go

```go
func countKConstraintSubstrings(s string, k int, queries [][]int) (ans []int64) {
cnt := [2]int{}
n := len(s)
d := make([]int, n)
for i := range d {
d[i] = n
}
pre := make([]int, n+1)
for i, j := 0, 0; j < n; j++ {
cnt[s[j]-'0']++
for cnt[0] > k && cnt[1] > k {
d[i] = j
cnt[s[i]-'0']--
i++
}
pre[j+1] = pre[j] + j - i + 1
}
for _, q := range queries {
l, r := q[0], q[1]
p := min(r+1, d[l])
a := (1 + p - l) * (p - l) / 2
b := pre[r+1] - pre[p]
ans = append(ans, int64(a+b))
}
return
}
```

#### TypeScript

```ts
function countKConstraintSubstrings(s: string, k: number, queries: number[][]): number[] {
const cnt: [number, number] = [0, 0];
const n = s.length;
const d: number[] = Array(n).fill(n);
const pre: number[] = Array(n + 1).fill(0);
for (let i = 0, j = 0; j < n; ++j) {
cnt[+s[j]]++;
while (Math.min(cnt[0], cnt[1]) > k) {
d[i] = j;
cnt[+s[i++]]--;
}
pre[j + 1] = pre[j] + j - i + 1;
}
const ans: number[] = [];
for (const [l, r] of queries) {
const p = Math.min(r + 1, d[l]);
const a = ((1 + p - l) * (p - l)) / 2;
const b = pre[r + 1] - pre[p];
ans.push(a + b);
}
return ans;
}
```

<!-- tabs:end -->
Expand Down
Loading
Loading