Skip to content

Commit 70a702d

Browse files
committed
feat: add solutions to lc problem: No.2537
No.2537.Count the Number of Good Subarrays
1 parent 56f8cb5 commit 70a702d

File tree

5 files changed

+175
-14
lines changed

5 files changed

+175
-14
lines changed

Diff for: solution/2500-2599/2537.Count the Number of Good Subarrays/README.md

+63-6
Original file line numberDiff line numberDiff line change
@@ -63,15 +63,15 @@ tags:
6363

6464
### 方法一:哈希表 + 双指针
6565

66-
如果一个子数组中包含 $k$ 对相同的元素,那么包含这个子数组的数组一定至少包含 $k$ 对相同的元素。
66+
如果一个子数组中包含 $k$ 对相同的元素,那么这个子数组一定包含至少 $k$ 对相同的元素。
6767

68-
我们用一个哈希表 $cnt$ 统计窗口内数组元素出现的次数,用 $cur$ 统计窗口内相同元素的对数,用 $i$ 维护窗口的左端点。
68+
我们用一个哈希表 $\textit{cnt}$ 统计窗口内数组元素出现的次数,用 $\textit{cur}$ 统计窗口内相同元素的对数,用 $i$ 维护窗口的左端点。
6969

70-
遍历数组 $nums$,我们将当前元素 $x$ 作为右端点,那么窗口内相同元素的对数将增加 $cnt[x]$,同时将 $x$ 的出现次数加一,即 $cnt[x] \leftarrow cnt[x] + 1$。接下来,我们循环判断移出左端点后窗口内相同元素的对数是否大于等于 $k$,如果大于等于 $k$,那么我们将左端点元素的出现次数减一,即 $cnt[nums[i]] \leftarrow cnt[nums[i]] - 1$,同时将窗口内相同元素的对数减去 $cnt[nums[i]]$,即 $cur \leftarrow cur - cnt[nums[i]]$,同时将左端点右移,即 $i \leftarrow i + 1$。此时窗口左端点以及左侧的所有元素都可以作为当前右端点的左端点,因此答案加上 $i + 1$。
70+
遍历数组 $\textit{nums}$,我们将当前元素 $x$ 作为右端点,那么窗口内相同元素的对数将增加 $\textit{cnt}[x]$,同时将 $x$ 的出现次数加一,即 $\textit{cnt}[x] \leftarrow \textit{cnt}[x] + 1$。接下来,我们循环判断移出左端点后窗口内相同元素的对数是否大于等于 $k$,如果大于等于 $k$,那么我们将左端点元素的出现次数减一,即 $\textit{cnt}[\textit{nums}[i]] \leftarrow \textit{cnt}[\textit{nums}[i]] - 1$,同时将窗口内相同元素的对数减去 $\textit{cnt}[\textit{nums}[i]]$,即 $\textit{cur} \leftarrow \textit{cur} - \textit{cnt}[\textit{nums}[i]]$,同时将左端点右移,即 $i \leftarrow i + 1$。此时窗口左端点以及左侧的所有元素都可以作为当前右端点的左端点,因此答案加上 $i + 1$。
7171

7272
最后,我们返回答案即可。
7373

74-
时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $nums$ 的长度。
74+
时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $\textit{nums}$ 的长度。
7575

7676
<!-- tabs:start -->
7777

@@ -104,8 +104,7 @@ class Solution {
104104
long ans = 0, cur = 0;
105105
int i = 0;
106106
for (int x : nums) {
107-
cur += cnt.getOrDefault(x, 0);
108-
cnt.merge(x, 1, Integer::sum);
107+
cur += cnt.merge(x, 1, Integer::sum) - 1;
109108
while (cur - cnt.get(nums[i]) + 1 >= k) {
110109
cur -= cnt.merge(nums[i++], -1, Integer::sum);
111110
}
@@ -165,6 +164,64 @@ func countGood(nums []int, k int) int64 {
165164
}
166165
```
167166

167+
#### TypeScript
168+
169+
```ts
170+
function countGood(nums: number[], k: number): number {
171+
const cnt: Map<number, number> = new Map();
172+
let [ans, cur, i] = [0, 0, 0];
173+
174+
for (const x of nums) {
175+
const count = cnt.get(x) || 0;
176+
cur += count;
177+
cnt.set(x, count + 1);
178+
179+
while (cur - (cnt.get(nums[i])! - 1) >= k) {
180+
const countI = cnt.get(nums[i])!;
181+
cnt.set(nums[i], countI - 1);
182+
cur -= countI - 1;
183+
i += 1;
184+
}
185+
186+
if (cur >= k) {
187+
ans += i + 1;
188+
}
189+
}
190+
191+
return ans;
192+
}
193+
```
194+
195+
#### Rust
196+
197+
```rust
198+
use std::collections::HashMap;
199+
200+
impl Solution {
201+
pub fn count_good(nums: Vec<i32>, k: i32) -> i64 {
202+
let mut cnt = HashMap::new();
203+
let (mut ans, mut cur, mut i) = (0i64, 0i64, 0);
204+
205+
for &x in &nums {
206+
cur += *cnt.get(&x).unwrap_or(&0);
207+
*cnt.entry(x).or_insert(0) += 1;
208+
209+
while cur - (cnt[&nums[i]] - 1) >= k as i64 {
210+
*cnt.get_mut(&nums[i]).unwrap() -= 1;
211+
cur -= cnt[&nums[i]];
212+
i += 1;
213+
}
214+
215+
if cur >= k as i64 {
216+
ans += (i + 1) as i64;
217+
}
218+
}
219+
220+
ans
221+
}
222+
}
223+
```
224+
168225
<!-- tabs:end -->
169226

170227
<!-- solution:end -->

Diff for: solution/2500-2599/2537.Count the Number of Good Subarrays/README_EN.md

+63-6
Original file line numberDiff line numberDiff line change
@@ -63,15 +63,15 @@ tags:
6363

6464
### Solution 1: Hash Table + Two Pointers
6565

66-
If a subarray contains $k$ pairs of identical elements, then an array that contains this subarray must contain at least $k$ pairs of identical elements.
66+
If a subarray contains $k$ pairs of identical elements, then this subarray must contain at least $k$ pairs of identical elements.
6767

68-
We use a hash table $cnt$ to count the number of occurrences of each element in the window, use $cur$ to count the number of pairs of identical elements in the window, and use $i$ to maintain the left endpoint of the window.
68+
We use a hash table $\textit{cnt}$ to count the occurrences of elements within the sliding window, a variable $\textit{cur}$ to count the number of identical pairs within the window, and a pointer $i$ to maintain the left boundary of the window.
6969

70-
We traverse the array $nums$, take the current element $x$ as the right endpoint, then the number of pairs of identical elements in the window will increase by $cnt[x]$, and the occurrence times of $x$ will be increased by one, i.e., $cnt[x] \leftarrow cnt[x] + 1$. Next, we loop to judge whether the number of pairs of identical elements in the window is greater than or equal to $k$ after removing the left endpoint. If it is greater than or equal to $k$, then we decrease the occurrence times of the left endpoint element by one, i.e., $cnt[nums[i]] \leftarrow cnt[nums[i]] - 1$, and decrease the number of pairs of identical elements in the window by $cnt[nums[i]]$, i.e., $cur \leftarrow cur - cnt[nums[i]]$, and move the left endpoint to the right, i.e., $i \leftarrow i + 1$. At this time, all elements to the left of the window left endpoint and the left endpoint itself can be used as the left endpoint of the current right endpoint, so the answer is increased by $i + 1$.
70+
As we iterate through the array $\textit{nums}$, we treat the current element $x$ as the right boundary of the window. The number of identical pairs in the window increases by $\textit{cnt}[x]$, and we increment the count of $x$ by 1, i.e., $\textit{cnt}[x] \leftarrow \textit{cnt}[x] + 1$. Next, we repeatedly check if the number of identical pairs in the window is greater than or equal to $k$ after removing the leftmost element. If it is, we decrement the count of the leftmost element, i.e., $\textit{cnt}[\textit{nums}[i]] \leftarrow \textit{cnt}[\textit{nums}[i]] - 1$, reduce the number of identical pairs in the window by $\textit{cnt}[\textit{nums}[i]]$, i.e., $\textit{cur} \leftarrow \textit{cur} - \textit{cnt}[\textit{nums}[i]]$, and move the left boundary to the right, i.e., $i \leftarrow i + 1$. At this point, all elements to the left of and including the left boundary can serve as the left boundary for the current right boundary, so we add $i + 1$ to the answer.
7171

7272
Finally, we return the answer.
7373

74-
The time complexity is $O(n)$, and the space complexity is $O(n)$, where $n$ is the length of the array $nums$.
74+
The time complexity is $O(n)$, and the space complexity is $O(n)$, where $n$ is the length of the array $\textit{nums}$.
7575

7676
<!-- tabs:start -->
7777

@@ -104,8 +104,7 @@ class Solution {
104104
long ans = 0, cur = 0;
105105
int i = 0;
106106
for (int x : nums) {
107-
cur += cnt.getOrDefault(x, 0);
108-
cnt.merge(x, 1, Integer::sum);
107+
cur += cnt.merge(x, 1, Integer::sum) - 1;
109108
while (cur - cnt.get(nums[i]) + 1 >= k) {
110109
cur -= cnt.merge(nums[i++], -1, Integer::sum);
111110
}
@@ -165,6 +164,64 @@ func countGood(nums []int, k int) int64 {
165164
}
166165
```
167166

167+
#### TypeScript
168+
169+
```ts
170+
function countGood(nums: number[], k: number): number {
171+
const cnt: Map<number, number> = new Map();
172+
let [ans, cur, i] = [0, 0, 0];
173+
174+
for (const x of nums) {
175+
const count = cnt.get(x) || 0;
176+
cur += count;
177+
cnt.set(x, count + 1);
178+
179+
while (cur - (cnt.get(nums[i])! - 1) >= k) {
180+
const countI = cnt.get(nums[i])!;
181+
cnt.set(nums[i], countI - 1);
182+
cur -= countI - 1;
183+
i += 1;
184+
}
185+
186+
if (cur >= k) {
187+
ans += i + 1;
188+
}
189+
}
190+
191+
return ans;
192+
}
193+
```
194+
195+
#### Rust
196+
197+
```rust
198+
use std::collections::HashMap;
199+
200+
impl Solution {
201+
pub fn count_good(nums: Vec<i32>, k: i32) -> i64 {
202+
let mut cnt = HashMap::new();
203+
let (mut ans, mut cur, mut i) = (0i64, 0i64, 0);
204+
205+
for &x in &nums {
206+
cur += *cnt.get(&x).unwrap_or(&0);
207+
*cnt.entry(x).or_insert(0) += 1;
208+
209+
while cur - (cnt[&nums[i]] - 1) >= k as i64 {
210+
*cnt.get_mut(&nums[i]).unwrap() -= 1;
211+
cur -= cnt[&nums[i]];
212+
i += 1;
213+
}
214+
215+
if cur >= k as i64 {
216+
ans += (i + 1) as i64;
217+
}
218+
}
219+
220+
ans
221+
}
222+
}
223+
```
224+
168225
<!-- tabs:end -->
169226

170227
<!-- solution:end -->

Diff for: solution/2500-2599/2537.Count the Number of Good Subarrays/Solution.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ public long countGood(int[] nums, int k) {
44
long ans = 0, cur = 0;
55
int i = 0;
66
for (int x : nums) {
7-
cur += cnt.getOrDefault(x, 0);
8-
cnt.merge(x, 1, Integer::sum);
7+
cur += cnt.merge(x, 1, Integer::sum) - 1;
98
while (cur - cnt.get(nums[i]) + 1 >= k) {
109
cur -= cnt.merge(nums[i++], -1, Integer::sum);
1110
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
use std::collections::HashMap;
2+
3+
impl Solution {
4+
pub fn count_good(nums: Vec<i32>, k: i32) -> i64 {
5+
let mut cnt = HashMap::new();
6+
let (mut ans, mut cur, mut i) = (0i64, 0i64, 0);
7+
8+
for &x in &nums {
9+
cur += *cnt.get(&x).unwrap_or(&0);
10+
*cnt.entry(x).or_insert(0) += 1;
11+
12+
while cur - (cnt[&nums[i]] - 1) >= k as i64 {
13+
*cnt.get_mut(&nums[i]).unwrap() -= 1;
14+
cur -= cnt[&nums[i]];
15+
i += 1;
16+
}
17+
18+
if cur >= k as i64 {
19+
ans += (i + 1) as i64;
20+
}
21+
}
22+
23+
ans
24+
}
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
function countGood(nums: number[], k: number): number {
2+
const cnt: Map<number, number> = new Map();
3+
let [ans, cur, i] = [0, 0, 0];
4+
5+
for (const x of nums) {
6+
const count = cnt.get(x) || 0;
7+
cur += count;
8+
cnt.set(x, count + 1);
9+
10+
while (cur - (cnt.get(nums[i])! - 1) >= k) {
11+
const countI = cnt.get(nums[i])!;
12+
cnt.set(nums[i], countI - 1);
13+
cur -= countI - 1;
14+
i += 1;
15+
}
16+
17+
if (cur >= k) {
18+
ans += i + 1;
19+
}
20+
}
21+
22+
return ans;
23+
}

0 commit comments

Comments
 (0)