• 概述

    前缀和是预处理数组的一种技巧,常用来计算子数组的和。
    定义前缀和数组数组前缀和 - 图1
    这种定义方式不包含0,前缀数组的维度和原数组维度相同。
    区间数组前缀和 - 图2的和为数组前缀和 - 图3。当数组前缀和 - 图4时,取数组前缀和 - 图5
    区间数组前缀和 - 图6的和为数组前缀和 - 图7数组前缀和 - 图8时,取数组前缀和 - 图9
    在Python中,可以用如下代码得到以此方式定义的前缀和:

    1. nums = [1, 2, 3]
    2. from itertools import accumulate
    3. pre = list(accumulate(nums))

    若定义前缀和数组为数组前缀和 - 图10
    则区间数组前缀和 - 图11的和为数组前缀和 - 图12。区间数组前缀和 - 图13的和为数组前缀和 - 图14
    在Python中,可以用如下代码得到以此方式定义的前缀和:

    1. nums = [1, 2, 3]
    2. pre = [0] * (len(nums) + 1)
    3. for i in range(len(nums)):
    4. pre[i+1] = pre[i] + nums[i]
    • 利用前缀和求解子数组和问题

    给定一个整数数组和一个整数 k,你需要找到该数组中和为 k 的连续的子数组的个数。
    来源:Leetcode560题
    链接:https://leetcode-cn.com/problems/subarray-sum-equals-k/
    参考解答:
    超时解答:复杂度数组前缀和 - 图15
    Python语言比较慢,其他语言复杂度为数组前缀和 - 图16的解法可以通过。

    1. class Solution:
    2. def subarraySum(self, nums: List[int], k: int) -> int:
    3. pre = list(accumulate(nums))
    4. ans = 0
    5. for i in range(len(nums)):
    6. for j in range(i, len(nums)):
    7. if pre[j] - (pre[i-1] if i != 0 else 0) == k:
    8. ans += 1
    9. return ans

    使用字典优化:复杂度数组前缀和 - 图17

    1. class Solution:
    2. def subarraySum(self, nums: List[int], k: int) -> int:
    3. s = 0
    4. d = collections.defaultdict(int)
    5. ans = 0
    6. d[0] = 1
    7. for i in range(len(nums)):
    8. s += nums[i] # s实际上就是前缀和,只不过没有写成数组的形式
    9. ans += d[s - k]
    10. d[s] += 1
    11. return ans