# Leetcode-前缀和系列

mhxin

## 1. 两数之和

``````def twoSum(self, nums: List[int], target: int) -> List[int]:
if not nums or len(nums) < 2:
return

# 使用字典保存target - nums[i]
prefix_sum = {}

n = len(nums)

for i in range(n):
if nums[i] in prefix_sum:
return [prefix_sum[nums[i]], i]

prefix[target-nums[i]] = i
``````

## 560. 和为K的子数组

1. 子数组中可能包含负数.
2. 并没有限定子数组长度.

\$nums[i]+...+nums[j]=sum(nums_{0,...,j})-sum(nums_{0,...,i-1})\$

``````
def subarraySum(nums, k):
if not nums:
return 0

n = len(nums)
res = 0

# 从索引为0的位置到当前位置的数组和
prefix_sum = 0

# 保存了所有前缀和及其对应的子数组个数
dicts = {0: 1}

for i in range(n):
prefix_sum += nums[i]

if prefix_sum - k in dicts:
res += dicts[prefix_sum - k]

#
dicts[prefix_sum] = dicts.get(prefix_sum, 0) + 1

return res
``````

## 1248. 统计「优美子数组」

• 1 <= nums.length <= 50000
• 1 <= nums[i] <= 10^5
• 1 <= k <= nums.length

``````def numberOfSubarrays(nums, k):
if not nums or len(nums) < k:
return 0

res = 0

# 值表示所有可能的奇数个数, 及其对应的子数组的个数
dicts = {0: 1}

# 表示从索引为0的位置到当前位置, 奇数的个数
prefix_sum = 0

n = len(nums)

for i in range(n):
if nums[i] % 2:
prefix_sum += 1

if prefix_sum - k in dicts:
res += dicts[prefix_sum - k]

if prefix_sum not in dicts:
dicts[prefix_sum] = 0

# 奇数个数为prefix_sum的子数组个数加1
dicts[prefix_sum] += 1

return res
``````

## 437. 路径总和 III

root = [10,5,-3,3,2,null,11,3,-2,null,1], sum = 8

``````      10
/  \
5   -3
/ \    \
3   2   11
/ \   \
3  -2   1

1.  5 -> 3
2.  5 -> 2 -> 1
3.  -3 -> 11
``````

``````def pathSum(self, root, sum):

self.dicts = {0: 1}
self.res = 0
def helper(root, prefix_sum, sum):
if not root:
return 0

prefix_sum += root.val

if prefix_sum - sum in self.dicts:
self.res += self.dicts[prefix_sum - sum]

self.dicts[prefix_sum] = self.dicts.get(prefix_sum, 0) + 1

helper(root.left, prefix_sum, sum)

helper(root.right, prefix_sum, sum)

# Note: 回到上一层时, 需要将当前的前缀和对应的路径数目减1
self.dicts[prefix_sum] -= 1

helper(root, 0, sum)
return res    ``````

82 声望
12 粉丝
0 条评论