一维前缀和和二维前缀和

本篇博文将向各位简单介绍什么是二维前缀和以及他的简单用法。

二维前缀和一维前缀和的理解:

那首先简单来看一下一维的前缀和:

一维前缀和和二维前缀和_第1张图片

        求数组a的下标1-4的一个和,那我们可以将每一个数依次相加起来,即当前下标存储的值表示当前下标以及之前的一个总和,即:

一维前缀和和二维前缀和_第2张图片

        因此,求下标1-4的和就用a[4]-a[0],同样的求下标2-4的和就用a[4]-a[1],这样就可以很快的求出某个区间的总和,同样的二维前缀和只是在以为前缀和的基础上加上一个维度,但是基础的思想是没有发生变化的。

一维前缀和和二维前缀和_第3张图片

接下来我们求坐标(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)

一维前缀和和二维前缀和_第4张图片

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开始的(本人觉得这里需要各位好好理解一下)。

你可能感兴趣的:(算法,数据结构,前缀和,c++)