leetcode308. 二维区域和检索(java)

265 篇文章 2 订阅
235 篇文章 0 订阅

leetcode308. 二维区域和检索

https://leetcode.com/problems/range-sum-query-2d-mutable
leetcode 308 原题链接

题目描述

给你一个 2D 矩阵 matrix,请计算出从左上角 (row1, col1) 到右下角 (row2, col2) 组成的矩形中所有元素的和。

实现 NumMatrix 类:

  1. NumMatrix(int[][] matrix) 用整数矩阵 matrix 初始化对象。
  2. void update(int row, int col, int val) 更新 matrix[row][col] 的值到 val 。
  3. int sumRegion(int row1, int col1, int row2, int col2) 返回矩阵 matrix 中指定矩形区域元素的 和 ,该区域由 左上角 (row1, col1) 和 右下角 (row2, col2) 界定。

示例1:
在这里插入图片描述
输入:[“NumMatrix”, “sumRegion”, “update”, “sumRegion”]
[[[[3, 0, 1, 4, 2], [5, 6, 3, 2, 1], [1, 2, 0, 1, 5], [4, 1, 0, 1, 7], [1, 0, 3, 0, 5]]], [2, 1, 4, 3], [3, 2, 2], [2, 1, 4, 3]]
输出:[null, 8, null, 10]
解释:
NumMatrix numMatrix = new NumMatrix([[3, 0, 1, 4, 2], [5, 6, 3, 2, 1], [1, 2, 0, 1, 5], [4, 1, 0, 1, 7], [1, 0, 3, 0, 5]]);
numMatrix.sumRegion(2, 1, 4, 3); // 返回 8 (即, 左侧红色矩形的和)
numMatrix.update(3, 2, 2); // 矩阵从左图变为右图
numMatrix.sumRegion(2, 1, 4, 3); // 返回 10 (即,右侧红色矩形的和)

注意:
矩阵 matrix 的值只能通过 update 函数来进行修改
你可以默认 update 函数和 sumRegion 函数的调用次数是均匀分布的
你可以默认 row1 ≤ row2,col1 ≤ col2

解法一 IndexTree

这个题就是indexTree 结构的二维拓展,首先了解下indexTree
indexTree 结构的规律在二维数组中同样适用,二维数组也是有不同的一维数组组成的。
假设二维数组中的 (i,j) 位置的值发生改变,
而行 i 对应的二进制形式为 0110100,则受影响的范围是行的【0110001 ~ 0110100】
而列 j 对应的二进制形式为 0111000,则受影响的范围是列的【0110001 ~ 0111000】
该行列范围内的所有组合都受影响,即 0110001 行的 【0110001 ~ 01111000】列受影响,0110010 行的 0110001 ~ 01111000 列受影响,以此类推。
即受到影响的范围是 【行的二进制形式最后一个1去掉然后加1 ~ 行的二进制】 和 【列的二进制形式最后一个1去掉然后加1 ~ 列的二进制】

代码演示

public class NumMatrix {
	private int[][] tree;
	private int[][] nums;
	private int N;
	private int M;

	public NumMatrix (int[][] matrix) {
		if (matrix.length == 0 || matrix[0].length == 0) {
			return;
		}
		N = matrix.length;
		M = matrix[0].length;
		tree = new int[N + 1][M + 1];
		nums = new int[N][M];
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < M; j++) {
				update(i, j, matrix[i][j]);
			}
		}
	}
//累加和
	private int sum(int row, int col) {
		int sum = 0;
		for (int i = row + 1; i > 0; i -= i & (-i)) {
			for (int j = col + 1; j > 0; j -= j & (-j)) {
				sum += tree[i][j];
			}
		}
		return sum;
	}

	/**
	 *
	 * @param row
	 * @param col
	 * @param val
	 */
	public void update(int row, int col, int val) {
		if (N == 0 || M == 0) {
			return;
		}
		int add = val - nums[row][col];
		nums[row][col] = val;
		for (int i = row + 1; i <= N; i += i & (-i)) {
			for (int j = col + 1; j <= M; j += j & (-j)) {
				tree[i][j] += add;
			}
		}
	}

//区域内累加和
	public int sumRegion(int row1, int col1, int row2, int col2) {
		if (N == 0 || M == 0) {
			return 0;
		}
		return sum(row2, col2) + sum(row1 - 1, col1 - 1) - sum(row1 - 1, col2) - sum(row2, col1 - 1);
	}

}

indexTree

数据结构算法:indexTree

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值