二维前缀和如何写?

121 阅读3分钟

最近在努力学习算法阿,学到了前缀和这一知识点,

由于天赋不够,努努力来凑,

决定写下什么来记录一下。

首先,什么是前缀和?

好吧,其实我也不太清楚(#捂脸),我的印象就是相当于一个高中数列。数列求和的亚子,相当于记录前n个的和。当我们需要算某个数组中某个区域的和,那么前缀和就很方便了。 比如说求[n.m] 的数SmSn\color{red}{Sm-Sn}即可。

那么前缀和如何求呢,我们可以构造一个前缀和数组,注意:前缀和下标都是从一开始。s(m,n)表示的就是从(m,n)带(1,1)所围成的矩阵中所有数字的和 比如说s(3,3)就是 就是(3,3)到(1,1)之间围成的所有数字的和

CF041076FBE54F1BE0FE30EF0F3B84E1.jpg

EDC1BFE07727866A381021B49CE5E6C9.jpg

我们如果要算(2,2)到(3,3)之间形成的子矩阵,那么就可以借助前缀和数组来算s(3,3) - s (3,1)-s(1,3) + s(1,1) 注意这个(m,n)代表的是一个正方形,并不是坐标,不要想象成某一个点了,他代表的就是某个矩阵中的数,边界并不是某个点,我当时一直是这么想的,不知道有没有人跟我一样有个错误的想法。

关于那个式子怎么来的,大家可以自己画图看看,利用的就是容斥原理,我表示电脑画图还不太会,就拍照看看了(#捂脸) 反正 某个子区域的所有和公式就是比如说x2,y2x1y1之间围成的区域就是S(x2,y2)s(x2,y11)s(x11,y2)+s(x11,y11)\color{red}{比如说 x2,y2 到x1, y1之间围成的区域就是 S(x2,y2)-s(x2,y1-1)-s(x1-1,y2)+s(x1-1,y1-1)}

那么前缀和又是怎么来算的呢?

前缀和就是也可以利用拆分算

63AB00506BA57C1C367910D5925F7639.jpg

比如说我们要算s(3,3) 那么把它分成四部分 ,我们要算的s(3,3) 就可以表示为 s(3,2) + s (2,3) -s(2,2) +a(3,3)

所以 求前缀和的公式就是 S(m,n)=s(m1,n)+s(m,n1)s(m1,n1)+a(m,n)\color{skyblue}{S(m,n) = s(m-1,n)+s(m,n-1)-s(m-1,n-1)+a(m,n)}

至于为什么减,自己可以写写看,反正只要记住 坐标所代表的是那个矩形就行,不是某一个点

这个题目对应有的leetcode题 leetcode

go代码

type NumMatrix struct {
     sums [][]int
}


func Constructor(matrix [][]int) NumMatrix {
    m:=len(matrix)
    if m==0{
        return NumMatrix{}
    }
    n:=len(matrix[0])
    sums := make([][]int,m+1)
for i := 0; i <= m; i++ {
        sums[i] = make([]int, n+1)  //初始化前缀和数组
    }

    for i:=0;i<m;i++{
        for j := 0;j<n;j++{
            sums[i+1][j+1] = sums[i][j+1] + sums[i+1][j] - sums[i][j] + matrix[i][j]
        }  //就是记几个公式
    }
    return NumMatrix{sums}
}


func (this *NumMatrix) SumRegion(row1 int, col1 int, row2 int, col2 int) int {
    return this.sums[row2+1][col2+1] - this.sums[row2+1][col1] -this.sums[row1][col2+1] + this.sums[row1][col1] 
}



所需要注意的是,由于题目所给的数组是从0,0开始,我们就需要开大一个开成,m+1 n+1,按照对应填进去.

后记

最后,看了一下,写的很乱,主要也是给自己记录一下学习过程,发现写文章真的要考虑很多东西阿,优美的文案,精美的排版,精确的格式。 所以要成为一名好的写作手不是一件很容易的事,所以要多向大佬学习。