[LeetCode] Range Sum Query 2D - Mutable 二维区域和检索 - 可变

简介:

Given a 2D matrix matrix, find the sum of the elements inside the rectangle defined by its upper left corner (row1, col1) and lower right corner (row2, col2).

Range Sum Query 2D
The above rectangle (with the red border) is defined by (row1, col1) = (2, 1) and (row2, col2) = (4, 3), which contains sum = 8.

Example:

Given matrix = [
  [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]
]
sumRegion(2, 1, 4, 3) -> 8
update(3, 2, 2)
sumRegion(2, 1, 4, 3) -> 10

Note:

  1. The matrix is only modifiable by the update function.
  2. You may assume the number of calls to update and sumRegion function is distributed evenly.
  3. You may assume that row1 ≤ row2 and col1 ≤ col2.

这道题让我们求二维区域和检索,而且告诉我们数组中的值可能变化,这是之前那道Range Sum Query 2D - Immutable的拓展,由于我们之前做过一维数组的可变和不可变的情况Range Sum Query - MutableRange Sum Query - Immutable,那么为了能够通过OJ,我们还是需要用到树状数组Binary Indexed Tree(参见Range Sum Query - Mutable),其查询和修改的复杂度均为O(logn),那么我们还是要建立树状数组,我们根据数组中的每一个位置,建立一个二维的树状数组,然后还需要一个getSum函数,以便求得从(0, 0)到(i, j)的区间的数字和,然后在求某一个区间和时,就利用其四个顶点的区间和关系可以快速求出,参见代码如下:

解法一:

// Binary Indexed Tree 
class NumMatrix {
public:
    NumMatrix(vector<vector<int>> &matrix) {
        if (matrix.empty() || matrix[0].empty()) return;
        mat.resize(matrix.size() + 1, vector<int>(matrix[0].size() + 1, 0));
        bit.resize(matrix.size() + 1, vector<int>(matrix[0].size() + 1, 0));
        for (int i = 0; i < matrix.size(); ++i) {
            for (int j = 0; j < matrix[i].size(); ++j) {
                update(i, j, matrix[i][j]);
            }
        }
    }

    void update(int row, int col, int val) {
        int diff = val - mat[row + 1][col + 1];
        for (int i = row + 1; i < mat.size(); i += i&-i) {
            for (int j = col + 1; j < mat[i].size(); j += j&-j) {
                bit[i][j] += diff;
            }
        }
        mat[row + 1][col + 1] = val;
    }

    int sumRegion(int row1, int col1, int row2, int col2) {
        return getSum(row2 + 1, col2 + 1) - getSum(row1, col2 + 1) - getSum(row2 + 1, col1) + getSum(row1, col1);
    }
    
    int getSum(int row, int col) {
        int res = 0;
        for (int i = row; i > 0; i -= i&-i) {
            for (int j = col; j > 0; j -= j&-j) {
                res += bit[i][j];
            }
        }
        return res;
    } 
    
private:
    vector<vector<int>> mat;
    vector<vector<int>> bit;
};

我在网上还看到了另一种解法,这种解法并没有用到树状数组,而是利用了列之和,所谓列之和,就是(i, j)就是(0, j) + (1, j) + ... + (i, j) 之和,相当于把很多个一维的区间之和拼到了一起,那么我们在构造函数中需要建立起这样一个列之和矩阵,然后再更新某一个位置时,我们只需要将该列中改变的位置下面的所有数字更新一下即可,而在求某个区间和时,只要将相差的各列中对应的起始和结束的行上的值的差值累加起来即可,参见代码如下:

解法二:

// Column Sum
class NumMatrix {
public:
    NumMatrix(vector<vector<int>> &matrix) {
        if (matrix.empty() || matrix[0].empty()) return;
        mat = matrix;
        colSum.resize(matrix.size() + 1, vector<int>(matrix[0].size(), 0));
        for (int i = 1; i < colSum.size(); ++i) {
            for (int j = 0; j < colSum[0].size(); ++j) {
                colSum[i][j] = colSum[i - 1][j] + matrix[i - 1][j];
            }
        }
    }

    void update(int row, int col, int val) {
        for (int i = row + 1; i < colSum.size(); ++i) {
            colSum[i][col] += val - mat[row][col];
        }
        mat[row][col] = val;
    }

    int sumRegion(int row1, int col1, int row2, int col2) {
        int res = 0;
        for (int j = col1; j <= col2; ++j) {
            res += colSum[row2 + 1][j] - colSum[row1][j];
        } 
        return res;
    }

private:
    vector<vector<int>> mat;
    vector<vector<int>> colSum;
};

本文转自博客园Grandyang的博客,原文链接:二维区域和检索 - 可变[LeetCode] Range Sum Query 2D - Mutable ,如需转载请自行联系原博主。

相关文章
|
8月前
|
算法
力扣240 搜索二维矩阵II
力扣240 搜索二维矩阵II
|
8月前
|
Go
golang力扣leetcode 240.搜索二维矩阵II
golang力扣leetcode 240.搜索二维矩阵II
47 0
|
7月前
|
机器学习/深度学习 算法 数据挖掘
LeetCode题目74:搜索二维矩阵
LeetCode题目74:搜索二维矩阵
|
8月前
|
算法
【Leetcode 74】搜索二维矩阵 —— 二分查找|矩阵
给你一个满足下述两条属性的`m x n`整数矩阵:每行中的整数从左到右按非严格递增顺序排列。每行的第一个整数大于前一行的最后一个整数
|
8月前
|
索引 Python
leetcode-307:区域和检索 - 数组可修改
leetcode-307:区域和检索 - 数组可修改
41 0
|
8月前
|
JavaScript SoC
leetcode-304:二维区域和检索 - 矩阵不可变
leetcode-304:二维区域和检索 - 矩阵不可变
64 0
|
8月前
|
索引 Python
leetcode-303:区域和检索 - 数组不可变
leetcode-303:区域和检索 - 数组不可变
34 0
|
4月前
|
Unix Shell Linux
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
本文提供了几个Linux shell脚本编程问题的解决方案,包括转置文件内容、统计词频、验证有效电话号码和提取文件的第十行,每个问题都给出了至少一种实现方法。
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
|
5月前
|
Python
【Leetcode刷题Python】剑指 Offer 32 - III. 从上到下打印二叉树 III
本文介绍了两种Python实现方法,用于按照之字形顺序打印二叉树的层次遍历结果,实现了在奇数层正序、偶数层反序打印节点的功能。
65 6
|
5月前
|
搜索推荐 索引 Python
【Leetcode刷题Python】牛客. 数组中未出现的最小正整数
本文介绍了牛客网题目"数组中未出现的最小正整数"的解法,提供了一种满足O(n)时间复杂度和O(1)空间复杂度要求的原地排序算法,并给出了Python实现代码。
133 2