0.总结

  • 子数组和子序列是两个完全不同的概念
  • 本题的主要思想是前缀和+映射表的使用
  • 博客来源:LawsonAbs@CSDN

1.​​题目​​

2.思想

3.代码

from copy import copy 
class Solution:
def subarraySum(self, nums: List[int], k: int) -> int:
prefix_sum = [0] * (len(nums)+1)
sum_cnt = {0:1} # 记录每个前缀和出现的次数
res = 0 # 最后的结果
for i in range(len(nums)):
prefix_sum[i+1] = prefix_sum[i] + nums[i] # 当前子缀和
res += sum_cnt.get(prefix_sum[i+1]-k,0) # 先找出
sum_cnt[prefix_sum[i+1]] = sum_cnt.get(prefix_sum[i+1],0) + 1
return res

4.

如果将子数组改成子序列,那么思想就是采用深搜 的方法,

  • step1 先对数组进行排序
  • step2.如何控制重复? -> 从左往右遍历的时候添加一个起始位置,同时判断当前这个数和下一个数是否相等,如果相等,则继续下移

得到的代码就如下:

from copy import copy 
class Solution:
def subarraySum(self, nums: List[int], k: int) -> int:
nums.sort()
vis = [0]*len(nums)
total = 0
res = []
cur = []
for start in range(len(nums)):
# 如果这里 nums[start] == nums[start-1]
if start>=1 and nums[start] == nums[start-1]:
continue
vis[start] = 1
cur.append(nums[start])
self.dfs(start,nums[start]+total,k,res,vis,nums,cur)
vis[start] = 0
cur.pop()
print(res)
return len(res)

# i表示当前所在的位置
# vis 表示节点是否已经访问
def dfs(self,start,total,k,res,vis,nums,cur):
# if total > k:
# return
if total == k:
res.append(copy(cur)) #
# print(res)
return
for i in range(start+1,len(nums)):
if vis[i] == 0:
if nums[i] + total > k: # 这里直接剪枝,因为数组已经有序
break
vis[i] = 1
cur.append(nums[i])
self.dfs(i,nums[i]+total,k,res,vis,nums,cur)
vis[i] = 0
cur.pop()

只不过,这里的复杂度,可能