K 个不同整数的子数组

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

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

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

示例 1:

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

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

提示:

1 < = A . l e n g t h < = 20000 1 < = A [ i ] < = A . l e n g t h 1 < = K < = A . l e n g t h 1 <= A.length <= 20000\\ 1 <= A[i] <= A.length\\ 1 <= K <= A.length 1<=A.length<=200001<=A[i]<=A.length1<=K<=A.length

  1. 思路
    对于一个固定的左边界来说,满足「恰好存在 K 个不同整数的子区间」的右边界 不唯一,且形成区间。

示例 1:左边界固定的时候,恰好存在 2 2 2 个不同整数的子区间为 [ 1 , 2 ] , [ 1 , 2 , 1 ] , [ 1 , 2 , 1 , 2 ] [1,2],[1,2,1],[1,2,1,2] [1,2],[1,2,1],[1,2,1,2],总数为 3 3 3。其值为下标 3 − 1 + 1 3 - 1 + 1 31+1,即区间 [ 1..3 ] [1..3] [1..3] 的长度。
在这里插入图片描述
须要找到左边界固定的情况下,满足「恰好存在 K 个不同整数的子区间」最小右边界和最大右边界。对比以前我们做过的,使用双指针解决的问题的问法基本都会出现「最小」、「最大」这样的字眼。

把原问题转换成为容易求解的问题

友情提示:这里把 「恰好」 转换成为 「最多」须要一点求解「双指针(滑动窗口)」问题的经验。建立在熟练掌握这一类问题求解思路的基础上。

把「恰好」改成「最多」就可以使用双指针一前一后交替向右的方法完成,这是因为 对于每一个确定的左边界,最多包含 KK 种不同整数的右边界是唯一确定的,并且在左边界向右移动的过程中,右边界或者在原来的地方,或者在原来地方的右边。

而「最多存在 K K K 个不同整数的子区间的个数」与「恰好存在 K K K 个不同整数的子区间的个数」的差恰好等于「最多存在 K − 1 K - 1 K1 个不同整数的子区间的个数」。
在这里插入图片描述
因为原问题就转换成为求解「最多存在 K K K 个不同整数的子区间的个数」与 「最多存在 K − 1 K - 1 K1 个不同整数的子区间的个数」,它们其实是一个问题。

方法:双指针(滑动窗口)
实现函数 a t M o s t W i t h K D i s t i n c t ( A , K ) atMostWithKDistinct(A, K) atMostWithKDistinct(A,K) ,表示「最多存在 KK 个不同整数的子区间的个数」。于是 a t M o s t W i t h K D i s t i n c t ( A , K ) − a t M o s t W i t h K D i s t i n c t ( A , K − 1 ) atMostWithKDistinct(A, K) - atMostWithKDistinct(A, K - 1) atMostWithKDistinct(A,K)atMostWithKDistinct(A,K1) 即为所求。
复杂度分析:

时间复杂度: O ( N ) O(N) O(N),这里 N N N 是输入数组的长度;
空间复杂度: O ( N ) O(N) O(N),使用了常数个变量、频数数组的长度为 N + 1 N + 1 N+1

class Solution {
private:
    int atmostWithKDistinct(vector<int>A,int k) {
        int left = 0, right = 0;
        int len = A.size();
        vector<int> cnt(len + 1, 0);
        int count = 0, res = 0;
        while (right < len) {
            if (cnt[A[right]] == 0) count++;
            cnt[A[right]]++;
            right++;
            while (count > k) {
                cnt[A[left]]--;
                if (cnt[A[left]] == 0) count--;
                left++;
            }
            res += right - left;
        }
        return res;
    }
public:
    int subarraysWithKDistinct(vector<int>& A, int K) {
        return atmostWithKDistinct(A,K)-atmostWithKDistinct(A,K-1);
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值