这个题要活用hash和前缀和的思想
给定一个整数数组和一个整数 k,你需要找到该数组中和为 k 的连续的子数组的个数。
ps:
- 数组的长度为 [1, 20,000]。
- 数组中元素的范围是 [-1000, 1000] ,且整数 k 的范围是 [-1e7, 1e7]
一刷:
直接暴力,那么时间是O(),跑不了
前缀和:从0项到当前项的总和
那么第i到第j的和就是第j的前缀和减去第i的前缀和
class Solution:
def subarraySum(self, nums: List[int], k: int) -> int:
presums = []
presum = 0
num = 0
for i in range(len(nums)):
if i == 0:
presum += 0
presums.append(presum)
for j in range(i, len(nums)):
if i == 0:
presum += nums[j]
presums.append(presum)
if presums[j+1] - presums[i] == k:
num += 1
return num
利用前缀和我们依然要计算i到j的前缀和,时间是O(),还是跑不了
那就说明还能继续优化,用hash存访 {前缀值差值,出现次数} 就可以把获得前缀值差值的时间缩小到O(1)了
class Solution:
def subarraySum(self, nums: List[int], k: int) -> int:
d = { 0 : 1 } #字典(哈希表),当k-k=0时在hash表中
presum = 0
count = 0
for i in nums:
presum += i
if presum - k in d:
count += d[presum - k]
if presum in d:
d[presum] += 1
if presum not in d:
d[presum] = 1
return count
整个算法时间复杂度为O(n)