在算法面试中,前缀和与差分算法是解决数组区间问题的高效工具,能够将暴力解法的O(n²)复杂度优化至O(n)。本文通过LeetCode第1300-1399题中的典型例题,详细讲解这两类算法的实战应用,帮助读者掌握区间查询与修改的核心技巧。
算法基础:前缀和与差分的数学原理
前缀和(Prefix Sum)通过预处理数组构建前缀和数组,实现区间和的O(1)查询;差分(Difference Array)则通过构造差分数组,将区间修改转化为单点操作。两者结合可高效解决区间统计、范围更新类问题。
前缀和的定义与性质
对于数组arr,其前缀和数组prefix定义为:
prefix[0] = 0
prefix[i] = arr[0] + arr[1] + ... + arr[i-1]
则区间[l, r]的和为prefix[r+1] - prefix[l]。
差分的定义与性质
对于数组arr,其差分数组diff定义为:
diff[0] = arr[0]
diff[i] = arr[i] - arr[i-1] (i > 0)
对区间[l, r]增加val时,只需执行diff[l] += val和diff[r+1] -= val,最后通过前缀和还原数组。
典型例题解析
1310. 子数组异或查询(前缀异或应用)
题目链接:docs/solutions/1300-1399/xor-queries-of-a-subarray.md
核心思路:异或运算具有自反性(x^x=0)和交换律,适合构建前缀异或数组。设prefix_xor[i]为前i个元素的异或结果,则区间[l, r]的异或值为prefix_xor[r+1] ^ prefix_xor[l]。
代码实现:
def xorQueries(arr, queries):
n = len(arr)
prefix_xor = [0] * (n + 1)
for i in range(n):
prefix_xor[i+1] = prefix_xor[i] ^ arr[i]
res = []
for l, r in queries:
res.append(prefix_xor[r+1] ^ prefix_xor[l])
return res
复杂度分析:预处理O(n),查询O(1),整体O(n + q)(q为查询次数)。
1343. 大小为K且平均值大于等于阈值的子数组数目(滑动窗口实现)
核心思路:转化为区间和问题,需满足sum(arr[l..r]) >= k * threshold。使用固定窗口滑动,维护窗口和并实时判断。
代码实现:
def numOfSubarrays(arr, k, threshold):
target = k * threshold
window_sum = sum(arr[:k])
count = 1 if window_sum >= target else 0
for i in range(k, len(arr)):
window_sum += arr[i] - arr[i-k]
if window_sum >= target:
count += 1
return count
算法对比:前缀和解法需O(n)空间,滑动窗口优化为O(1)空间,适用于大数据量场景。
进阶应用:前缀和与双指针结合
1358. 包含所有三种字符的子字符串数目(滑动窗口+计数)
题目链接:docs/solutions/1300-1399/number-of-substrings-containing-all-three-characters.md
核心思路:使用不定长滑动窗口记录字符出现次数,当窗口包含a、b、c时,收缩左边界并统计有效子串数量。
代码实现:
def numberOfSubstrings(s):
count = {'a':0, 'b':0, 'c':0}
left = 0
res = 0
for right in range(len(s)):
count[s[right]] += 1
while all(v > 0 for v in count.values()):
res += len(s) - right
count[s[left]] -= 1
left += 1
return res
复杂度分析:时间O(n),空间O(1),每个字符最多被访问两次。
实战技巧与避坑指南
- 边界处理:前缀和数组多开一个空间(prefix[0] = 0),避免区间计算时的越界判断。
- 数据类型:处理大数组时注意整数溢出,Python无需担心但其他语言需使用long类型。
- 算法选择:
- 静态区间查询 → 前缀和
- 动态区间修改 → 差分
- 定长区间统计 → 滑动窗口
相关题目推荐
| 题目编号 | 题目名称 | 算法类型 |
|---|---|---|
| 1300 | 转变数组后最接近目标值的数组和 | 二分查找+前缀和 |
| 1310 | 子数组异或查询 | 前缀异或 |
| 1343 | 大小为K且平均值大于等于阈值的子数组数目 | 滑动窗口 |
| 1358 | 包含所有三种字符的子字符串数目 | 不定长滑动窗口 |
完整题解可参考:docs/solutions/1300-1399/index.md
总结与升华
前缀和与差分算法是处理数组区间问题的"多功能工具",通过空间换时间的策略,将复杂的区间操作转化为简单的数组访问。掌握这些技巧不仅能应对LeetCode中等难度题目,更为解决高频面试题奠定基础。建议结合docs/01_array/01_15_array_two_pointers.md中的双指针技巧进行综合练习,提升算法组合应用能力。
关注后续系列文章,我们将深入讲解树状数组、线段树等高级数据结构,进一步拓展区间问题的解决方案。收藏本文,算法进阶不迷路!
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



