一、前缀和
前缀和(Prefix Sum)是一种重要的预处理技术,能够高效解决区间求和问题。
1、基本概念
对于数组 nums
,其前缀和数组 prefix
定义为:
prefix[0] = 0
prefix[i] = nums[0] + nums[1] + ... + nums[i-1] (i > 0)
核心思想:
- 预处理:预先计算并存储前缀和
- 快速查询:通过前缀和数组可以在O(1)时间内计算任意区间和
2、前缀和实现
class PrefixSum:
def __init__(self, nums):
self.prefix = [0] * (len(nums) + 1)
for i in range(len(nums)):
self.prefix[i + 1] = self.prefix[i] + nums[i]
# 查询区间[i,j]的和(闭区间)
def query(self, i, j):
return self.prefix[j + 1] - self.prefix[i]
nums = [1, 2, 3, 4, 5]
ps = PrefixSum(nums)
print(ps.query(1, 3)) # 输出:9 (2+3+4)
print(ps.query(0, 4)) # 输出:15 (1+2+3+4+5)
二、差分
差分算法是一种高效处理区间更新问题的技术,特别适用于需要对数组的某个区间进行统一增减操作的场景。
1、基本概念
差分数组是原数组的相邻元素之差构成的数组。对于原数组 arr
,其差分数组 diff
定义为:
diff[0] = arr[0]
diff[i] = arr[i] - arr[i-1] (i > 0)
核心思想
- 区间更新:在差分数组上进行单点修改,等价于在原数组上进行区间更新
- 前缀和还原:对差分数组求前缀和即可得到原数组
2、差分算法实现
基本实现
class Difference:
def __init__(self, nums):
self.diff = [0] * len(nums)
self.diff[0] = nums[0]
for i in range(1, len(nums)):
self.diff[i] = nums[i] - nums[i - 1]
# 给区间[i,j]增加val(val可为负数)
def increment(self, i, j, val):
self.diff[i] += val
if j + 1 < len(self.diff):
self.diff[j + 1] -= val
# 返回结果数组
def result(self):
res = [0] * len(self.diff)
res[0] = self.diff[0]
for i in range(1, len(self.diff)):
res[i] = res[i - 1] + self.diff[i]
return res
nums = [1, 2, 3, 4, 5]
df = Difference(nums)
df.increment(1, 3, 2) # 给索引1到3的元素加2
print(df.result()) # 输出:[1, 4, 5, 6, 5]
"""
1.差分数组的定义
设原始数组为A[],差分数组D[]满足:
D[0] = A[0]
D[k] = A[k] - A[k-1] (k ≥ 1)
于是 A[k] = D[0] + D[1] + … + D[k] (前缀和)
也就是说,只要改某个D值,就会影响从这个位置开始一直到末尾的所有A值。
我们希望:
A[i] += val
A[i+1] += val
...
A[j] += val
但后面的 A[j+1], A[j+2], … 保持不变。
用差分数组做这件事只需两步:
• 在 D[i] 加 val
→ 从 A[i] 开始的所有元素都加了 val。
• 在 D[j+1] 减 val(如果 j+1 存在)
→ 从 A[j+1] 开始又把多出来的 val 减掉,从而抵消掉之前的影响。
"""