
二维前缀和、二维差分、离散化技巧
class048 二维前缀和、二维差分、离散化技巧
二维前缀和
-
目的:生成一个结构,以后查询二维数组任何范围上的累加和都是O(1)的操作
-
做法:生成二维前缀和数组sum,sum[i][i]代表从(0.0)~ (i,j)范围内所有数值的和
-
自己等于自己左边数+自己上边数-自己左上数+自己
-
注意:实际操作中往往补第0行,第0列来简化判断,例如原来的第数组0行第0列的值既没有左数,上数,也没有左上数
1
sum[i][j] += sum[i][j-1] + sum[i-1][j] - sum[i-1][j-1];
-
要求:查询 从(a,b)~ (c,d)范围内数字的累加和
1
num = sum[c][d] - sum[c][b-1] - sum[a-1][d] + sum[a-1][b-1];
1 | class NumMatrix { |
- 做法:构建二维前缀和数组,从(0,0)一直遍历到(n-1,m-1),时间复杂度为O(n*m * min(n,m)),判断一个正方形边界全为1,只需判断外边正方形数字的累加和减去里面正方形数字的累加和是否等于周长
1 | class Solution { |
二维差分
-
在二维数组中,如果经历如下的过程
批量的做如下的操作,每个操作都有独立的a、b、c、d、v
void add(a, b, c, d, v) : 左上角(a,b)到右下角(c,d)范围上,每个数字+v,怎么快速处理?
-
通过下述的add方法和build方法实现(往往在真实数据周围围上一圈0来方便运算,数组长宽都加2)
1 | public static void add(int a,int b,int c,int d,int k ){ |
1 | public static void build(){ |
- 循环遍历二维矩阵,检查以这个点开始,长为h,宽为m的区域的累加和是否为0,如果是,则这个位置可以贴邮票(区域全部加1)
- 但是每个位置都可能被多个邮票贴过,所以不能在原数组修改,维护一个差分数组来完成贴邮票的操作
- 为了能够快速得到区域累加和,维护一个前缀和数组
- 最后如果原数组某个位置是0,而差分数组这个位置同样是0,说明这个位置没有贴上邮票(没有办法覆盖所有的空格),返回false
1 | class Solution { |
离散化技巧
- 统计力场的四条边的坐标,由于会出现0.5,可将坐标乘以2
- 由于坐标的值可能会非常大,无法维护那么大的差分数组,所以离散化横纵坐标,不管坐标原来的值有多大,只返回它在横坐标数组中的索引并加1
- 二维差分和二维前缀和复原
1 | class Solution { |
本文是原创文章,采用CC BY-NC-SA 4.0协议,完整转载请注明来自Heaven

