Python前缀和、差分

一、前缀和

前缀和(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 减掉,从而抵消掉之前的影响。
"""

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值