leetcode 992 双指针 区间个数

在这里插入图片描述

之前做的题,都是问区间最长长度或者最优结果,但这次返回的是满足条件得区间个数,就不能用之前的思路了,因为可能会忽略情况。
第一种解法就是,在左指针移动前,先记录下满足条件的个数,代码如下:

class Solution:
    def subarraysWithKDistinct(self, A: List[int], K: int) -> int:
        l, r, ret = 0, 0, 0
        c = Counter()

        while r < len(A):
            c[A[r]] += 1

            # 移动左指针
            while l<=r and len(c) > K:
                c[A[l]] -= 1
                if c[A[l]] == 0: del c[A[l]]
                l += 1

            # # 统计信息
            tmp = l
            s = []
            while tmp<=r and len(c) == K:
                ret += 1
                s.append(A[tmp])
                c[A[tmp]] -= 1
                if c[A[tmp]] == 0: del c[A[tmp]]
                tmp += 1
            
            for t in s:
                c[t] += 1

            r += 1
        
        return ret

还是之前的双指针模板,但是加了一个O(ret)的复杂度,已经不是O(N)了,速度慢。

解法二:两次遍历
这是一个O(N)的很强的解法。要写一个函数,返回满足条件得子区间的所有子区间。比如[1, 2, 3, 3, 5], 3 例子中,[1, 2, 3, 3] 和 [2, 3, 3, 5] 是满足条件得,他们两个的子区间个数是可以在右指针移动过程中计算的,1+2+3+4。但这里面包含小于K的情况,再调用K-1,即可把这部分可能性排除,代码如下:

class Solution:
    def subarraysWithKDistinct(self, A: List[int], K: int) -> int:
        def getSubArray(A, K):
            l, r, ret = 0, 0, 0
            c = Counter()

            while r < len(A):
                c[A[r]] += 1

                while l <= r and len(c) > K:
                    c[A[l]] -= 1
                    if c[A[l]] == 0: del c[A[l]]
                    l += 1
                    
                ret += r-l+1
                r += 1
            
            return ret
        
        return getSubArray(A, K) - getSubArray(A, K-1)

这个题很不一样的一点在于,要求不同的数字数目必须为K,而我们需要转化为<=K才能用双指针移动。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值