题目
给定一个正整数数组 A,如果 A 的某个子数组中不同整数的个数恰好为 K,则称 A 的这个连续、不一定不同的子数组为好子数组。
(例如,[1,2,3,1,2] 中有 3 个不同的整数:1,2,以及 3。)
返回 A 中好子数组的数目。
示例
输入:A = [1,2,1,2,3], K = 2
输出:7
解释:恰好由 2 个不同整数组成的子数组:[1,2], [2,1], [1,2], [2,3], [1,2,1], [2,1,2], [1,2,1,2].
提示
- 1 <= A.length <= 20000
- 1 <= A[i] <= A.length
- 1 <= K <= A.length
题解
- 恰好为K个不同整数:最多包含K个不同整数-最多包含K-1个整数
- 双指针求子数组中包含最多K个整数的个数
- 用一个变量count来记录区间[left, right]内的不同整数的个数
- 若count>k:则左指针右移,并将哈希表内A[left]对应的次数减1,当A[left]的次数为1时,count减1,此时区间内无A[left]这个整数
- 对于res += right - left + 1:对于区间[left, right]其最多含有K个不同的整数,它包含以right为右端点的子数组的个数为:right-left+1。例如:[1, 2, 1, 2] k=2代表包含2个不同整数的子数组有4个,left = 0, right = 3。分别为:[2], [2, 1], [2, 1, 2], [2, 1, 2, 1]
参考代码
class Solution {
public int subarraysWithKDistinct(int[] A, int K) {
//恰好为 K 可以变为 最多 为 k 个 减去 最多为k - 1个
return subarraysWithMostK(A, K) - subarraysWithMostK(A, K - 1);
}
public int subarraysWithMostK(int[] A, int k) {
int left = 0, right = 0;
int count = 0;
int res = 0;
Map<Integer> map = new HashMap<>();
while(right < A.length()) {
map.put(A[right], map.getOrDefault(A[right], 0)+1);
if(map.get(A[right++]) == 1) {
count++;
}
while(count > k) {
map.put(A[left], map.get(A[left])-1);
if(map.get(A[left] == 0)) {
count--;
}
left++;
}
res += right - left + 1;
}
return res;
}
}