📢 欢迎来到万事技术论坛!本站仅讨论合法编程技术话题,严禁外挂/作弊/黑产/盗版内容,违者封号。

精华前缀和与差分:区间问题的万能钥匙

captain_algo 活跃会员

遇到「区间求和」「区间批量加减」,先想这两个。

一维前缀和

# pre[i] 表示 nums[0..i-1] 的和,pre[0] = 0
pre = [0]
for x in nums:
    pre.append(pre[-1] + x)

# 区间 [l, r] 的和(下标从 0 开始)
s = pre[r + 1] - pre[l]

查询从 O(n) 降到 O(1),代价是 O(n) 预处理。

二维前缀和

# pre[i][j] = 左上角 (0,0) 到 (i-1,j-1) 的矩形和
pre[i][j] = (pre[i-1][j] + pre[i][j-1] - pre[i-1][j-1] + matrix[i-1][j-1])

# 子矩形 (x1,y1) 到 (x2,y2) 的和
s = (pre[x2+1][y2+1] - pre[x1][y2+1] - pre[x2+1][y1] + pre[x1][y1])

画个图记:大矩形减掉上面和左面,加回被重复减的左上角。

差分数组:区间批量加减

「给区间 [l, r] 每个元素都加 3」做 m 次,朴素做法 O(m·n)。差分数组 O(m + n):

diff = [0] * (n + 1)
diff[l] += 3
diff[r + 1] -= 3          # 只改两个端点

# 最后前缀和还原
for i in range(1, n + 1):
    diff[i] += diff[i - 1]

本质:把「区间操作」变成「两个点的操作」。

经典例题套路

题型 解法
和为 K 的子数组个数 前缀和 + 哈希表计数
航班预订统计(每单给区间 +1) 差分
矩阵区域和 二维前缀和
数组中满足某条件的最长区间 前缀和 + 单调性/二分

和为 K 的子数组(前缀和 + 哈希)

from collections import defaultdict

def subarray_sum(nums, k):
    cnt, cur = 0, 0
    seen = defaultdict(int)
    seen[0] = 1                    # 空前缀
    for x in nums:
        cur += x
        cnt += seen[cur - k]       # 之前出现过 cur-k,说明中间这段和为 k
        seen[cur] += 1
    return cnt

seen[0] = 1 这个初始化最容易漏,漏了就数不到从下标 0 开始的子数组。

楼主 · 2026-09-28 13:21 · 浏览 2
lin_dev 活跃会员

二维前缀和那个公式我总是记反,后来自己总结的口诀:"右下角减上面减左面加左上角",画个图就忘不掉了。

1楼 · 2026-09-28 13:21
登录 后即可参与回复。