知识总结:前缀和与差分 | 豆包MarsCode AI刷题

92 阅读2分钟

在计算机科学中,前缀和差分是两种高效处理区间操作和序列问题的基础算法工具。它们通过对数据的预处理,大幅优化了解决某些问题的效率,特别适用于一维或多维数组上的区间查询和更新操作。

前缀和(Prefix Sum)

定义

前缀和是一种通过累加数组前面元素的值,构造出的一个新数组。给定一个数组 arr,它的前缀和数组 prefix 定义为:

prefix[i]=arr[0]+arr[1]++arr[i]prefix[i]=arr[0]+arr[1]+⋯+arr[i]

公式:

对于任意区间 [l,r] 的区间和,可以通过前缀和快速计算:

sum[l,r]=prefix[r]prefix[l1]sum[l,r]=prefix[r]−prefix[l−1]

(注意:当 l=0 时,区间和直接为prefix[r])。

实现步骤:

  1. 构造前缀和数组:使用一次遍历,累计每个位置的和。
  2. 查询区间和:通过简单的减法操作实现。

优点:

  • 提高区间和查询的效率,从 O(n)降低到 O(1)。
  • 适用于需要多次区间查询的场景。

二维前缀和

那么将前缀和从一维推广到二维,我们的区间修改可以变成一个二维矩阵里实现子矩阵求和了

  • s[i][j]为以(i,j)为右下角,左上角为(0,0)的子矩阵的所有元素和
  • 那么使用简单的容斥原理,不难得出s【i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j]
  • 我们也可以通过简单的容斥原理快速求出一个子矩阵的和

多维前缀和

通过容斥原理,不难得出高维前缀和的计算时间复杂度为O(2kN)O(2^{k}N),k为维度 当k很大显然该算法不再适用了。我们可以采用逐维前缀和

k维前缀和就相当于k次求和,那么我们每次考虑一个维度,固定其他维度,这样k次求和。时间复杂度为O(kN)O(kN)这样就是可考虑的了


差分(Difference Array)

定义

差分是一种通过记录数组中相邻元素的差值,快速实现区间修改的方法。给定一个数组 arr,它的差分数组 diff 定义为:

diff[i]=arr[i]arr[i1],diff[0]=arr[0]diff[i]=arr[i]−arr[i−1] ,diff[0]=arr[0]

核心思想

在原数组上进行区间更新时,仅需修改差分数组的两个位置:

  • 在 l 位置增加 v,即 diff[l]+=v
  • 在 r+1位置减去 v,即 diff[r+1]−=v(若 r+1 不越界)。
  • 这样的话,对a[1]到a[L-1]和a[r+1]到a[n]都没有影响
  • 最后,通过对差分数组取前缀和,可还原出修改后的原数组。

优点

  • 提高区间修改的效率,从 O(n) 降低到 O(1)。
  • 适用于多次区间修改的场景。

二维差分

那么将差分从一维推广到二维,我们的区间修改可以变成一个二维矩阵里实现子矩阵修改了

  • 对于原矩阵a[i][j],构造差分矩阵b[i][j]使得a数组是b数组的二维前缀和
  • 要对(x1,y1)为左上角,(x2,y2)为右下角的子矩阵中所有数加上C,只需要进行下面操作
  • b[x1][y1]+=c;b[x2+1][y2+1]+=c;b[x1][y2+1]-=c;b[x2+1][y1]-=c;
  • 最后对着差分数组做一次二维前缀和就得到了经过多次修改的原二维数组了