Subarrays with K Different Integers

update Feb 11 2019, 20:02

LeetCodearrow-up-right

Given an array A of positive integers, call a (contiguous, not necessarily distinct) subarray of A good if the number of different integers in that subarray is exactly K.

(For example, [1,2,3,1,2] has 3 different integers: 1, 2, and 3.)

Return the number of good subarrays of A.

Example 1:

Input: A = [1,2,1,2,3], K = 2
Output: 7
Explanation: Subarrays formed with exactly 2 different integers: [1,2], [2,1], [1,2], [2,3], [1,2,1], [2,1,2], [1,2,1,2].

Example 2:

Input: A = [1,2,1,3,4], K = 3
Output: 3
Explanation: Subarrays formed with exactly 3 different integers: [1,2,1,3], [2,1,3], [1,3,4].

Note:

  1. 1 <= A.length <= 20000

  2. 1 <= A[i] <= A.length

  3. 1 <= K <= A.length

Basic Idea:

拿到题目之后就会发现如果要硬算,直接求解distinct element number为 Ksubarray 个数是比较困难的,因为这类题目一般会使用双指针或者sliding window求解,而要求所有subarray的个数就需要维持许多窗口中subarray的特征。

看了Lee215的解法之后豁然开朗,我们可以写一个function getAtMostK()来求 distinct element number <= K subarray 的个数,这样只需要返回 getAtMost(K) - getAtMost(K-1) 就可以了。

具体地,如何实现 getAtMostK() 呢?用sliding window,保证window中不同元素个数 <= K,每次右边界右移一位,而每次当前窗口中所有以right结尾的subarray的个数就是 right - left + 1,只要把每个元素结尾的符合条件的subarray个数相加,就是总的个数。

整体时间复杂度为 O(2N), 空间复杂度 O(N);

Java Code:

update Mar 25, 2019

Update concise java code

这道题的本质是每次将right指针右移一位,所以我们可以利用一个for loop。在loop中每次检查window中是否只有小于等于K个不同的数字。合理利用++让code更短。

update Mar 26, 2019

Update: Without "atMostK()"

其实之所以需要转化成 atMostK 问题,是因为直接用双指针的时候我们需要处理重复问题,也就是当右指针right固定时,满足条件左指针的位置不是唯一的,于是我们就有了另一种思路,即右指针仍然每次前进一格,每次当窗口满足条件时,我们考虑所有满足条件的左指针的范围i~j,则对于当前右指针为止,满足条件的subarray就有 j-i+1 个。

-----------------------------

Jul 7, 2021

Update: with atMostK 新的写法

其实这种做法可以理解为对于每个右边界right,找到最左端的左边界left使得之间部分只有小于等于K个不同元素,然后计算共有多少个以right结尾的subarray。因为我们每次只计算以right结尾的,而且我们考虑到了所有的right,所以不会有重复的情况。

Last updated