题目:和为K的子数组
题解
首先明确题目中给出的数组是整数数组,包含负数/正数/0,其次数组是 无序 的,再然后需要找的是和为K的 子数组 ,子数组是 连续 的原数组片段且 非空
解法1:暴力枚举
依次固定子数组左端的边界,再枚举子数组右端的边界,时间复杂度O(N^2),空间复杂度O(1)
代码
class Solution(object):
def subarraySum(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: int
"""
ret = 0
size = len(nums)
for i in range(0, size):
count = 0
for j in range(i, size):
count += nums[j]
ret = ret + 1 if count == k else ret
return ret
暴力枚举的方法,我们计算一个子数组的和都是遍历子数组的方式取计算,或许可以换个方式??
如图中,第二种计算方法就让我们想到了前缀和去计算sumBlue-sumOrange。
解法2:利用前缀和
计算出数组的前缀和,当计算到i位置的前缀和时,向前寻找等于preSum[i]-k的前缀和
特殊处理:在前缀和数组前多引入一个0处理边界值问题
代码
class Solution(object):
def subarraySum(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: int
"""
ret = 0
preSum = []
preSum.append(0)
count = 0
for e in nums:
count += e
for num in preSum:
ret = ret + 1 if count - num == k else ret
preSum.append(count)
return ret
搞什么???时间复杂度还是O(N^2),而且空间复杂度还变为O(N)了
稍安勿躁!!!
我们会发现,我们在走到某个位置时会向前会找某个特定的值,我们寻找的方式是遍历,那岂不是浪费了查询高手哈希表,所以我们结合一下哈希,改良一下代码!!!
代码优化
class Solution(object):
def subarraySum(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: int
"""
# 前缀和+哈希优化
ret = 0
preSum = list()
hash = dict()
preSum.append(0)
hash[0] = 1
count = 0
for e in nums:
count += e
res = hash.get(count - k)
if res is not None:
ret += res
if count in hash:
hash[count] += 1
else:
hash[count] = 1
return ret
小小总结:前缀和是用来快速得到某个连续区间的和(也不一定是和,可能是乘积或其他),付出的代价是空间,必须存储下前缀和,典型的用空间换时间