Subarrays with K Different Integers

题目
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].

*思路

这个题是思考过程可以从暴力O(n^2)解法evolve到三指针的O(n)解法

暴力解法是首先用一个循环遍历数组的每个元素i
For every starting point i, try to find number of valid subarrays starting from i
例如[1,2,2], K = 2
i = 0时,我们可以得出的valid subarrays有[1,2]和[1,2,2]这2个
Do this for every i in array A, you'll get the answer

暴力解法的缺点是当正在遍历元素 i 时,你每次都得用另一个指针j从i的位置开始遍历后面的所有元素才能知道有哪些valid subarrays。所以时间复杂度是O(n^2)

可以看出每次遍历一个新的元素i,指针j总是得回撤到i的位置然后开始遍历后面的元素
双指针的算法多数都是利用求解答案的某些特性,让我们无需回撤指针从而达到降低一个级别的时间复杂度

例如[1,2,1,2,3], K = 2
i = 0时, valid subarrays有[1,2], [1,2,1], [1,2,1,2] (一共3个)
我们可以有一根指针left让它指向从i开始第一个遇到的valid subarray的末端(用一个dict1 keep track of number of distinct numbers in A[i...left], 如果len(dict1)等于K,则找到了left的位置)

用一根right指针指向最后一个遇到的valid subarray的末端(用一个dict2 keep track of number of distinct numbers in A[i...right], 如果len(dict2)等于K,而且right如果再向右移动就会导致len(dict2) > K)
在我们的这个例子input里,left = 1, right = 3

那么你会发现
number of valid subarrays starting from i is just equal to right - left + 1 = 3 - 1 + 1 = 3
这3个valid subarrays分别是A[i...left], A[i...left+1], A[i...right]

i = 1时
也需要找到相对于i = 1的对应的left和right指针,就可以计算出number of valid subarrays starting from i
当i = 1时,我们就不用考虑A[0]。A[0...left]本来是valid的,但是A[1...left]就不一定valid了。
所以left指针要向右边探,使得A[1...left]也变得valid。同理right指针要向右移动使得A[1...right]变得valid。
当重新计算出相对于i = 1的对应的left和right指针,我们又知道了number of valid subarrays starting from i = 1了

以此类推遍历完i = 0,1,2...n就行了
期间涉及到3个指针(i, left, right),由于他们全程都只需要向右移动,直到数组结尾,所以时间复杂度是O(n)

答案

class Solution(object):
    def subarraysWithKDistinct(self, A, K):
        """
        :type A: List[int]
        :type K: int
        :rtype: int
        """
        # window[number] -> occurrences of number
        window1 = {}
        window2 = {}
        
        ans = 0
        left, right = 0, 0
        for i in range(len(A)):
            # Move left pointer to closet place s.t [i...left] has exactly K distinct chars
            # Move right pointer to as far as possible s.t [i...right] has exactly K distinct chars
            while left < len(A):
                if len(window1) == K:
                    break
                window1[A[left]] = window1.get(A[left], 0) + 1
                left += 1
            if len(window1) < K:
                continue
                
            while right < len(A):
                if len(window2) == K:
                    break
                window2[A[right]] = window2.get(A[right], 0) + 1
                right += 1

            while right < len(A):
                if A[right] not in window2:
                    break
                else:
                    window2[A[right]] = window2.get(A[right], 0) + 1
                    right += 1
            
            ans += (right - left + 1)

            window1[A[i]] -= 1
            if window1[A[i]] == 0:
                window1.pop(A[i])

            window2[A[i]] -= 1
            if window2[A[i]] == 0:
                window2.pop(A[i])
             
        return ans
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342