Skip to content

feat: add solutions to lc problem: No.2537 #4355

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
Apr 15, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,15 @@ tags:

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

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

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

遍历数组 $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$。
遍历数组 $\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$。

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

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

<!-- tabs:start -->

Expand Down Expand Up @@ -104,8 +104,7 @@ class Solution {
long ans = 0, cur = 0;
int i = 0;
for (int x : nums) {
cur += cnt.getOrDefault(x, 0);
cnt.merge(x, 1, Integer::sum);
cur += cnt.merge(x, 1, Integer::sum) - 1;
while (cur - cnt.get(nums[i]) + 1 >= k) {
cur -= cnt.merge(nums[i++], -1, Integer::sum);
}
Expand Down Expand Up @@ -165,6 +164,64 @@ func countGood(nums []int, k int) int64 {
}
```

#### TypeScript

```ts
function countGood(nums: number[], k: number): number {
const cnt: Map<number, number> = new Map();
let [ans, cur, i] = [0, 0, 0];

for (const x of nums) {
const count = cnt.get(x) || 0;
cur += count;
cnt.set(x, count + 1);

while (cur - (cnt.get(nums[i])! - 1) >= k) {
const countI = cnt.get(nums[i])!;
cnt.set(nums[i], countI - 1);
cur -= countI - 1;
i += 1;
}

if (cur >= k) {
ans += i + 1;
}
}

return ans;
}
```

#### Rust

```rust
use std::collections::HashMap;

impl Solution {
pub fn count_good(nums: Vec<i32>, k: i32) -> i64 {
let mut cnt = HashMap::new();
let (mut ans, mut cur, mut i) = (0i64, 0i64, 0);

for &x in &nums {
cur += *cnt.get(&x).unwrap_or(&0);
*cnt.entry(x).or_insert(0) += 1;

while cur - (cnt[&nums[i]] - 1) >= k as i64 {
*cnt.get_mut(&nums[i]).unwrap() -= 1;
cur -= cnt[&nums[i]];
i += 1;
}

if cur >= k as i64 {
ans += (i + 1) as i64;
}
}

ans
}
}
```

<!-- tabs:end -->

<!-- solution:end -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,15 @@ tags:

### Solution 1: Hash Table + Two Pointers

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.
If a subarray contains $k$ pairs of identical elements, then this subarray must contain at least $k$ pairs of identical elements.

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.
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.

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$.
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.

Finally, we return the answer.

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

<!-- tabs:start -->

Expand Down Expand Up @@ -104,8 +104,7 @@ class Solution {
long ans = 0, cur = 0;
int i = 0;
for (int x : nums) {
cur += cnt.getOrDefault(x, 0);
cnt.merge(x, 1, Integer::sum);
cur += cnt.merge(x, 1, Integer::sum) - 1;
while (cur - cnt.get(nums[i]) + 1 >= k) {
cur -= cnt.merge(nums[i++], -1, Integer::sum);
}
Expand Down Expand Up @@ -165,6 +164,64 @@ func countGood(nums []int, k int) int64 {
}
```

#### TypeScript

```ts
function countGood(nums: number[], k: number): number {
const cnt: Map<number, number> = new Map();
let [ans, cur, i] = [0, 0, 0];

for (const x of nums) {
const count = cnt.get(x) || 0;
cur += count;
cnt.set(x, count + 1);

while (cur - (cnt.get(nums[i])! - 1) >= k) {
const countI = cnt.get(nums[i])!;
cnt.set(nums[i], countI - 1);
cur -= countI - 1;
i += 1;
}

if (cur >= k) {
ans += i + 1;
}
}

return ans;
}
```

#### Rust

```rust
use std::collections::HashMap;

impl Solution {
pub fn count_good(nums: Vec<i32>, k: i32) -> i64 {
let mut cnt = HashMap::new();
let (mut ans, mut cur, mut i) = (0i64, 0i64, 0);

for &x in &nums {
cur += *cnt.get(&x).unwrap_or(&0);
*cnt.entry(x).or_insert(0) += 1;

while cur - (cnt[&nums[i]] - 1) >= k as i64 {
*cnt.get_mut(&nums[i]).unwrap() -= 1;
cur -= cnt[&nums[i]];
i += 1;
}

if cur >= k as i64 {
ans += (i + 1) as i64;
}
}

ans
}
}
```

<!-- tabs:end -->

<!-- solution:end -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ public long countGood(int[] nums, int k) {
long ans = 0, cur = 0;
int i = 0;
for (int x : nums) {
cur += cnt.getOrDefault(x, 0);
cnt.merge(x, 1, Integer::sum);
cur += cnt.merge(x, 1, Integer::sum) - 1;
while (cur - cnt.get(nums[i]) + 1 >= k) {
cur -= cnt.merge(nums[i++], -1, Integer::sum);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use std::collections::HashMap;

impl Solution {
pub fn count_good(nums: Vec<i32>, k: i32) -> i64 {
let mut cnt = HashMap::new();
let (mut ans, mut cur, mut i) = (0i64, 0i64, 0);

for &x in &nums {
cur += *cnt.get(&x).unwrap_or(&0);
*cnt.entry(x).or_insert(0) += 1;

while cur - (cnt[&nums[i]] - 1) >= k as i64 {
*cnt.get_mut(&nums[i]).unwrap() -= 1;
cur -= cnt[&nums[i]];
i += 1;
}

if cur >= k as i64 {
ans += (i + 1) as i64;
}
}

ans
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
function countGood(nums: number[], k: number): number {
const cnt: Map<number, number> = new Map();
let [ans, cur, i] = [0, 0, 0];

for (const x of nums) {
const count = cnt.get(x) || 0;
cur += count;
cnt.set(x, count + 1);

while (cur - (cnt.get(nums[i])! - 1) >= k) {
const countI = cnt.get(nums[i])!;
cnt.set(nums[i], countI - 1);
cur -= countI - 1;
i += 1;
}

if (cur >= k) {
ans += i + 1;
}
}

return ans;
}