[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).html

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. java

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:
ide

  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)的區間的數字和,而後在求某一個區間和時,就利用其四個頂點的區間和關係能夠快速求出,參見代碼以下:函數

 

解法一:post

// 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) 之和,至關於把不少個一維的區間之和拼到了一塊兒,那麼咱們在構造函數中須要創建起這樣一個列之和矩陣,而後再更新某一個位置時,咱們只須要將該列中改變的位置下面的全部數字更新一下便可,而在求某個區間和時,只要將相差的各列中對應的起始和結束的行上的值的差值累加起來便可,參見代碼以下:url

 

解法二:spa

// 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;
};

 

相似題目:code

Range Sum Query 2D - Immutablehtm

Range Sum Query - Mutable

Range Sum Query - Immutable

 

參考資料:

https://leetcode.com/discuss/70948/15ms-easy-to-understand-java-solution

https://leetcode.com/discuss/71169/java-2d-binary-indexed-tree-solution-clean-and-short-17ms

 

LeetCode All in One 題目講解彙總(持續更新中...)

相關文章
相關標籤/搜索