diff --git a/solution/2500-2599/2537.Count the Number of Good Subarrays/README.md b/solution/2500-2599/2537.Count the Number of Good Subarrays/README.md index b366f85a1bbd0..0a52588d7d99b 100644 --- a/solution/2500-2599/2537.Count the Number of Good Subarrays/README.md +++ b/solution/2500-2599/2537.Count the Number of Good Subarrays/README.md @@ -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}$ 的长度。 @@ -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); } @@ -165,6 +164,64 @@ func countGood(nums []int, k int) int64 { } ``` +#### TypeScript + +```ts +function countGood(nums: number[], k: number): number { + const cnt: Map = 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, 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 + } +} +``` + diff --git a/solution/2500-2599/2537.Count the Number of Good Subarrays/README_EN.md b/solution/2500-2599/2537.Count the Number of Good Subarrays/README_EN.md index 16f4e856b5de9..05f4963cfa1eb 100644 --- a/solution/2500-2599/2537.Count the Number of Good Subarrays/README_EN.md +++ b/solution/2500-2599/2537.Count the Number of Good Subarrays/README_EN.md @@ -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}$. @@ -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); } @@ -165,6 +164,64 @@ func countGood(nums []int, k int) int64 { } ``` +#### TypeScript + +```ts +function countGood(nums: number[], k: number): number { + const cnt: Map = 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, 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 + } +} +``` + diff --git a/solution/2500-2599/2537.Count the Number of Good Subarrays/Solution.java b/solution/2500-2599/2537.Count the Number of Good Subarrays/Solution.java index bd58024b9094a..749124e323478 100644 --- a/solution/2500-2599/2537.Count the Number of Good Subarrays/Solution.java +++ b/solution/2500-2599/2537.Count the Number of Good Subarrays/Solution.java @@ -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); } diff --git a/solution/2500-2599/2537.Count the Number of Good Subarrays/Solution.rs b/solution/2500-2599/2537.Count the Number of Good Subarrays/Solution.rs new file mode 100644 index 0000000000000..18ff33d9f67f6 --- /dev/null +++ b/solution/2500-2599/2537.Count the Number of Good Subarrays/Solution.rs @@ -0,0 +1,25 @@ +use std::collections::HashMap; + +impl Solution { + pub fn count_good(nums: Vec, 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 + } +} diff --git a/solution/2500-2599/2537.Count the Number of Good Subarrays/Solution.ts b/solution/2500-2599/2537.Count the Number of Good Subarrays/Solution.ts new file mode 100644 index 0000000000000..58a6d91cbca44 --- /dev/null +++ b/solution/2500-2599/2537.Count the Number of Good Subarrays/Solution.ts @@ -0,0 +1,23 @@ +function countGood(nums: number[], k: number): number { + const cnt: Map = 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; +}