给你一个整数数组 nums
和一个整数 k
,请你返回 nums
中 好 子数组的数目。
一个子数组 arr
如果有 至少 k
对下标 (i, j)
满足 i < j
且 arr[i] == arr[j]
,那么称它是一个 好 子数组。
子数组 是原数组中一段连续 非空 的元素序列。
示例 1:
输入:nums = [1,1,1,1,1], k = 10 输出:1 解释:唯一的好子数组是这个数组本身。
示例 2:
输入:nums = [3,1,4,3,2,2,4], k = 2 输出:4 解释:总共有 4 个不同的好子数组: - [3,1,4,3,2,2] 有 2 对。 - [3,1,4,3,2,2,4] 有 3 对。 - [1,4,3,2,2,4] 有 2 对。 - [4,3,2,2,4] 有 2 对。
提示:
1 <= nums.length <= 10^5
1 <= nums[i], k <= 10^9
提示 1
For a fixed index l, try to find the minimum value of index r, such that the subarray is not good
提示 2
When a number is added to a subarray, it increases the number of pairs by its previous appearances.
提示 3
When a number is removed from the subarray, it decreases the number of pairs by its remaining appearances.
提示 4
Maintain 2-pointers l and r such that we can keep in account the number of equal pairs.
解法:不定长滑动窗口 (求子数组个数)
相似题目:
LeetCode 713. 乘积小于 K 的子数组-CSDN博客
LeetCode 2799. 统计完全子数组的数目-CSDN博客
LeetCode 1358. 包含所有三种字符的子字符串数目-CSDN博客
LeetCode 2962. 统计最大元素出现至少 K 次的子数组-CSDN博客
LeetCode 2302. 统计得分小于 K 的子数组数目-CSDN博客
这些题都是类似的,真正理解后,虽百题,可知也。
class Solution {
public long countGood(int[] nums, int k) {
long ans = 0;
int n = nums.length;
int left = 0;
int right = 0;
long count = 0;
HashMap<Integer, Integer> window = new HashMap<>();
while (right < n) {
// nums[right]成对
if (window.merge(nums[right], 1, Integer::sum) >= 2) {
count += window.get(nums[right]) - 1;
}
while (count >= k) {
count -= window.get(nums[left])- 1;
if (window.merge(nums[left], -1, Integer::sum) == 0) {
window.remove(nums[left]);
}
left++;
}
ans += left;
right++;
}
return ans;
}
}
复杂度分析
- 时间复杂度:O(n),n 是 数组nums 的长度。
- 空间复杂度:O(1)。