本篇博文将向各位简单介绍什么是二维前缀和以及他的简单用法。
那首先简单来看一下一维的前缀和:
求数组a的下标1-4的一个和,那我们可以将每一个数依次相加起来,即当前下标存储的值表示当前下标以及之前的一个总和,即:
因此,求下标1-4的和就用a[4]-a[0],同样的求下标2-4的和就用a[4]-a[1],这样就可以很快的求出某个区间的总和,同样的二维前缀和只是在以为前缀和的基础上加上一个维度,但是基础的思想是没有发生变化的。
接下来我们求坐标(x,y)的一个前缀和:
根据图上颜色板块我们就可以知道以(x,y)为下标的一个前缀和公式为:
sums[x][y]=sums[x][y-1]+sums[x-1][y]-sums[x-1][y-1]+a[x][y];
以上公式便可以求出坐标(x,y)到坐标(0,0)的一个前缀和~ 那如何求一个区间的前缀和呢?既然求得了坐标(x,y)到坐标(0,0)的一个前缀和,那就将需要求的区间题目给出的坐标相减即可~
接下来我们具体来看一个例题,以下给出题目链接:304. 二维区域和检索 - 矩阵不可变 - 力扣(LeetCode)
class NumMatrix {
public:
vector> sums;
NumMatrix(vector>& matrix) {
int rlen=matrix.size();
int clen=matrix[0].size();
sums.resize(rlen+5,vector(clen+5));
for(int i=1;i<=rlen;i++){
for(int j=1;j<=clen;j++){
sums[i][j]=sums[i-1][j]+sums[i][j-1]-sums[i-1][j-1]+matrix[i-1][j-1];
}
}
}
int sumRegion(int r1, int c1, int r2, int c2) {
return sums[r2+1][c2+1]-sums[r2+1][c1]-sums[r1][c2+1]+sums[r1][c1];
}
};
以上代码即表示二维求区间前缀和的代码,其中和公式有所不同的是以下一行:
sums[i][j]=sums[i-1][j]+sums[i][j-1]-sums[i-1][j-1]+matrix[i-1][j-1];
标注有颜色部分不能写成matrix[i][j],假设我们求sums[1][1],但是实际上求的是坐标matrix[0][0]的一个前缀和,假设我们求的是sums[2][2],实际上我们求的是matrix[1][1]的一个前缀和,因为我们的i和j都是以1开始的(本人觉得这里需要各位好好理解一下)。