在过去,我常常使用这个方法来迅速求范围和。
比如数组arr=【1,2,3,4,5,6,】
我可以用公式sums[i]=sums[len(sums)-1]+arr[i]
来获得一个数组的范围和数组【1,3,6,10,15,21】
这样通过范围相减可以迅速求得范围和,而不需遍历。
leetcode560是这种方法的改良版。
题目:
给定一个整数数组和一个整数 k,你需要找到该数组中和为 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的增加,还会递增。