Leetcode560. 和为K的子数组——数组记录和的改良

在过去,我常常使用这个方法来迅速求范围和。

比如数组arr=【1,2,3,4,5,6,】

我可以用公式sums[i]=sums[len(sums)-1]+arr[i]

来获得一个数组的范围和数组【1,3,6,10,15,21】

这样通过范围相减可以迅速求得范围和,而不需遍历。

leetcode560是这种方法的改良版。

题目:

给定一个整数数组和一个整数 k,你需要找到该数组中和为 的连续的子数组的个数。

示例 1 :

输入:nums = [1,1,1], k = 2
输出: 2 , [1,1] 与 [1,1] 为两种不同的情况。

参考别人的方法,是这样的代码:

class Solution:
    def subarraySum(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: int
        """
        d={0:1}
        s,cnt=0,0
        for n in nums:
            s+=n
            cnt+=d.get(s-k,0)
            d[s]=d.get(s,0)+1
        return cnt

其中s是连续和,cnt是计数器。

仅说说for循环中的过程。

如果想要得到范围和是k的连续数组,那么因为当前的子数组和(从首元素开始求的)是s=a0+a1....ai

那么我们需要知道能不能有t=a0+a1...+aj(j<i)存在,使得sum(aj+1~ai)==k

因为aj+1~ai是所求满足的k这样我们需要知道t是不是存在的,那么也就是s-k是否存在。

如果存在,那么肯定是可以增加计数器了。

以上是考虑范围和各不相等的情况。

如果范围和有重复的呢?

比如:

1,-1,2,3的a0~a3与a2~a3的和是一样的。那么实际上cnt加的是这一个和的个数2.(因为s是连续的,可知这段和肯定是连续子数组求和得到的)。

最终有了以上代码。

比较值得注意的是初始化是存在k:v=0:1,这是考虑了恰好有范围从首元素开始求和的数量——1。

这个值最开始有且只能为1,不过随着求和恰好为0的增加,还会递增。

猜你喜欢

转载自blog.csdn.net/weixin_37373020/article/details/80981828