旺崽的博客

要么天赋异禀,要么天道酬勤

0%

LeetCode 992 K 个不同整数的子数组

题目链接

给定一个正整数数组 A,如果 A 的某个子数组中不同整数的个数恰好为 K,则称 A 的这个连续、不一定不同的子数组为好子数组。

(例如,[1,2,3,1,2] 中有 3 个不同的整数:1,2,以及 3)

返回 A 中好子数组的数目。

示例 1:

1
2
3
输入: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].

示例 2:

1
2
3
输入:A = [1,2,1,3,4], K = 3
输出:3
解释:恰好由 3 个不同整数组成的子数组:[1,2,1,3], [2,1,3], [1,3,4].

思维+双指针~
利用双指针,当我们固定左端点时,可以找到恰好存在 K 个不同整数的最大右边界 $R$,那么我们只需找到最小左边界 $L$,答案就是 $R-L+1$,那么这个最小左边界怎么找呢,我们可以再加一个指针,这个指针指向恰好存在 K-1 个不同整数的最大右边界 $R’$,答案就是 $R-R’$,AC代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Solution {
public:
int subarraysWithKDistinct(vector<int> &A, int K) {
int n = A.size();
vector<int> num1(n + 1), num2(n + 1);
int sum1 = 0, sum2 = 0;
int l1 = 0, l2 = 0, r = 0, ans = 0;
while (r < n) {
if (!num1[A[r]]) sum1++;
num1[A[r]]++;
if (!num2[A[r]]) sum2++;
num2[A[r]]++;
while (sum1 > K) {
num1[A[l1]]--;
if (!num1[A[l1]]) sum1--;
l1++;
}
while (sum2 > K - 1) {
num2[A[l2]]--;
if (!num2[A[l2]]) sum2--;
l2++;
}
ans += l2 - l1;
r++;
}
return ans;
}
};