前缀和的数学推导

在leetcode有一些题利用的是前缀和方法,很多时候都用的是图形法解,一开始还是有点费解的,特别是对于我这样不太擅长图形转化成公式的人来说。本文用的单纯的数学推导得到递推公式,理解的基础上直接用代码实现公式。
前缀和思路在于区域相减,以leetcode的304题为例子
S [ r o w 1 , r o w 2 ] [ c o l 1 , c o l 2 ] = Σ r o w 1 r o w 2 Σ c o l 1 c o l 2 M a t i x [ i ] [ j ] S[row1,row2][col1,col2] = \Sigma_{row1}^{row2}\Sigma_{col1}^{col2} Matix[i][j] S[row1,row2][col1,col2]=Σrow1row2Σcol1col2Matix[i][j]
其中, i ∈ [ r o w 1 , r o w 2 ] , j ∈ [ c o l 1 , c o l 2 ] i\in[row1,row2],j\in[col1,col2] i[row1,row2],j[col1,col2]
伪代码为

int sum = 0;
for i from row1 -> row2
    for j from col1 -> col2
        sum = sum + Matrix[i][j]
return sum

但是在上述求解过程中不难发现求解S[i][j]会反复计算Matrix[0][0],Matrix[0][1],Matrix[1][0]…求解区域越大前面的元素被求解调用的次数越多,其实不难发现就是存在重复子问题,可以考虑动态规划,借用之前图形就是
在这里插入图片描述
S [ D ] = S [ D t o t a l ] − S [ A ] − S [ B ] + S [ C ] S[D] =S[D_{total}] -S[A] - S[B] + S[C] S[D]=S[Dtotal]S[A]S[B]+S[C]
其中 S [ D t o t a l ] S[D_{total}] S[Dtotal] 为D区域右下角坐标到原点的求和。由上式不难发现,子问题被存储在数组S中,避免了反复对Matrix的求和。
针对 S [ D ] S[D] S[D]求解,计算公式为 S [ D x ] [ D y ] = Σ 0 D x Σ 0 D y M a t i x [ i ] [ j ] S[D_x][D_y] = \Sigma_{0}^{D_x}\Sigma_{0}^{D_y} Matix[i][j] S[Dx][Dy]=Σ0DxΣ0DyMatix[i][j] ,这个问题一样,反复求解之前数据,思路和之前一样,如果直接求解,就是遍历 $[0,D_x],[0,D_y] $区间,针对求和公式分解,定义 S [ k x ] [ k y ] S[k_x][k_y] S[kx][ky] 为坐标点k的,由原点到该坐标的方块区域内坐标点求和
在这里插入图片描述
因为 S [ k x − 1 ] [ k y ] = Σ 0 k x − 1 Σ 0 k y M a t r i x [ i ] [ j ] = Σ 0 k x − 1 M a t r i x [ i ] [ k y ] + Σ 0 k x − 1 Σ 0 k y − 1 M a t r i x [ i ] [ j ] S[k_x-1][k_y] =\Sigma_{0}^{k_x-1}\Sigma_{0}^{k_y}Matrix[i][j] = \Sigma_{0}^{k_x-1}Matrix[i][k_y] + \Sigma_{0}^{k_x-1}\Sigma_{0}^{k_y-1}Matrix[i][j] S[kx1][ky]=Σ0kx1Σ0kyMatrix[i][j]=Σ0kx1Matrix[i][ky]+Σ0kx1Σ0ky1Matrix[i][j]同理对于$ S[k_x][k_y-1] $不难推导得到,而 S [ k x − 1 ] [ k y − 1 ] = Σ 0 k x − 1 Σ 0 k y − 1 M a t r i x [ i ] [ j ] S[k_x -1][k_y-1] = \Sigma_{0}^{k_x-1}\Sigma_{0}^{k_y-1}Matrix[i][j] S[kx1][ky1]=Σ0kx1Σ0ky1Matrix[i][j]即为重叠区域,上述递推式子即只需要每次加上 Matrix[i][j] 即可,而无需反复求和,利用空间换时间
总结起来就是两个递推式
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值