题目来源
题目描述
class Solution {
public:
int subarraysWithKDistinct(vector<int>& nums, int k) {
}
};
题目解析
题意
- 给出一个由正整数构成数组 A ,如果 A 中一个子数组恰好有 K 个不同的数字,那么就称之为好子数组。
- 求一个数组 A 中的好子数组的个数。
分析
- 首先可以将问题转换:恰好由 K 个不同整数组成的子数组的个数 = 最多由 K 个不同整数组成的子数组的个数 - 最多由 K - 1 个不同整数组成的子数组的个数
- 然后问题就变成了求:最多由K个不同整数组成的子数组个数
- 用滑动窗口来做:滑动窗口中用到了左右两个指针,它们移动的思路是:以右指针作为驱动,拖着左指针向前走。右指针每次只移动一步,而左指针在内部 while 循环中每次可能移动多步。右指针是主动前移,探索未知的新区域;左指针是被迫移动,负责寻找满足题意的区间。
class Solution {
int helper(vector<int>& A, int K) {
int n = A.size(), res = 0, left = 0;
unordered_map<int, int> numCnt;
for (int i = 0; i < n; ++i) {
if (numCnt[A[i]] == 0) --K;
++numCnt[A[i]];
while (K < 0) { // 当窗口不满足要求时,移动left,寻找符号题意的区间
if (--numCnt[A[left]] == 0) ++K;
++left;
}
res += i - left + 1;
}
return res;
}
public:
int subarraysWithKDistinct(vector<int>& A, int K){
return helper(A, K) - helper(A, K - 1);
}
};
class Solution {
int helper(vector<int>& A, int K) {
int n = A.size(), res = 0, left = 0;
unordered_map<int, int> numCnt;
for (int i = 0; i < n; ++i) {
++numCnt[A[i]];
while (numCnt.size() > K) {
if (--numCnt[A[left]] == 0) numCnt.erase(A[left]);
++left;
}
res += i - left + 1;
}
return res;
}
public:
int subarraysWithKDistinct(vector<int>& A, int K){
return helper(A, K) - helper(A, K - 1);
}
};
class Solution {
public:
int subarraysWithKDistinct(vector<int>& A, int K) {
return helper(A, K) - helper(A, K - 1);
}
int helper(vector<int>& A, int K) {
int n = A.size(), res = 0, left = 0;
unordered_map<int, int> num2idx;
for (int i = 0; i < n; ++i) {
num2idx[A[i]] = i;
while (num2idx.size() > K) {
if (num2idx[A[left]] == left) num2idx.erase(A[left]);
++left;
}
res += i - left + 1;
}
return res;
}
};