给出一个整数数组nums和一个整数k,问该数组中有几个连续的子串和等于k。
解法1:没有任何优化暴力算法
假定这个子串为[i , j],0 <= i,j < len(nums), 那么i,j共有O(n^2)种组合,求每个子串的和时间复杂度为O(n),总时间复杂度为O(n^3)。
O(n^3)的算法当然是不可能通过的啦,代码就懒得写了。
解法2:利用了部分和的暴力算法
还是遍历i,j的O(n^2)种组合,每次遍历时i固定,j向前延伸,这样子串和的计算就可以用到前面计算的结果,在O(1)时间内得出子串和。
这种算法用C++写能通过,python会超时,充分暴露python效率低下的缺点。因为我的目的是学python,C++代码就不放了。
解法3:使用哈希表
记下标范围[0, i)的子串和为sum(i),则下标范围[i, j) 的子串和为sum(j) - sum(i),若能找到sum(j) - sum(i) == k,则找到一个子串和等于k,再进一步,若能找到一个比j小的i使,sum(j) - k == sum(i),则找到一个符合要求的子串。那么,可以用哈希表记录有多少个比j小的i,sum(i) == sum(j) - k。
具体做法是:声明一个字典d,key表示部分和,value表示有几个i使sum(i)等于这个部分和,遍历nums计算部分和,每次计算出一个部分和sum(j),就通过字典查看有几个比j小的i使得sum(j) - k == sum(i),即count += d[sum - k]。
代码如下:
扫描二维码关注公众号,回复:
1075587 查看本文章
class Solution(object): def subarraySum(self, nums, k): """ :type nums: List[int] :type k: int :rtype: int """ d = dict.fromkeys([0], 1) # key为sum[0, i)部分和,value为sum[0, i) == key的i的数量 sum = 0 cnt = 0 for i in range(0, len(nums)): sum += nums[i] if sum - k in d.keys(): cnt += d[sum - k] d[sum] = d.get(sum, 0) + 1 return cnt