LeetCode 304. Range Sum Query 2D - Immutable 二維區域和檢索 - 矩陣不可變(C++/Java)

題目:

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

Example:spa

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
sumRegion(1, 1, 2, 2) -> 11
sumRegion(1, 2, 2, 4) -> 12

 

Note:code

  1. You may assume that the matrix does not change.
  2. There are many calls to sumRegion function.
  3. You may assume that row1 ≤ row2 and col1 ≤ col2.

分析:

給定一個二維矩陣,求其子矩陣內全部元素的和。blog

若是每次調用sumRegion,遍歷範圍內全部元素的和,這種辦法可行可是並不可取。咱們先來看下面這個圖。element

上圖是求解一個矩形面積的圖畫 展現,能夠清楚的理解各個矩形塊之間的關係,咱們把矩形內的元素和比做矩形的面積。定義dp爲二維數組,dp[i][j]是以(i, j)元素爲右下角,能夠求得一個子矩陣內全部元素的和。那麼咱們把dp[i][j]的值想象成上圖中矩形的面積,大矩形的面積=去除右邊一列的面積+去除下邊一行的面積-重複的地方(左上角的面積)+當前小矩形塊的面積。it

此時當前的小矩形塊就是所給定的矩陣(i, j)位置的元素。io

去除右邊一列的面積也就是以(i, j-1)元素爲右下角的矩陣的元素和,實際上就是dp[i][j-1]。function

去除下邊一行的面積就是以(i-1, j)元素爲右下角的矩陣的元素和,實際上就是dp[i-1][j]。class

左上角的面積則是以(i-1, j-1)元素爲右下角的矩陣的元素和,實際上就是dp[i-1][j-1]。

藉此咱們能夠在O(mn)的時間內求的dp矩陣,接下來要求任意給定子矩陣的全部元素和,看下圖。

一樣仍是將矩陣內的元素和比做矩形的面積,此時右下角爲咱們所要求的矩形面積=大矩形面積-去除右邊區域的面積+去除下邊區域的面積+重複的地方(左上角的面積)。

此時咱們就能夠利用上邊所求的dp數組來快速求的結果。因爲給了範圍,也就是x1,y1,x2,y2,經過上面的圖咱們不難看出各個面積區域之間的關係。

實際上最後的結果也就是右下角的矩形面積。那麼

大矩形面積也就是以x2, y2爲右下角的矩陣的元素和,實際上就是dp[x2][y2]。

去除右邊區域的面積就是以x2, y1-1爲右下角的矩陣的元素和,實際上就是dp[x2][y1-1]。

去除下邊區域的面積就是以x1-1, y2爲右下角的矩陣的元素和,實際上就是dp[x1-1][y2]。

左上角的面積就是以x1-1, y1-1爲右下角的矩陣的元素和,實際上就是dp[x1-1][y1-1]。

最後的結果就是dp[x2][y2] - dp[x2][y1-1] - dp[x1-1][y2] + dp[x1-1][y1-1]。

小技巧就是開闢的dp數組長寬能夠比原數組多1,這樣就不用了處理邊界條件了。

程序:

C++

class NumMatrix {
public:
    NumMatrix(vector<vector<int>>& matrix) {
        if(matrix.empty())
            return;
        int m = matrix.size();
        int n = matrix[0].size();
        
        dp = vector<vector<int>>(m+1, vector<int>(n+1, 0));
        for(int i = 1; i <= m; ++i){
            for(int j = 1; j <= n; ++j){
                dp[i][j] = dp[i-1][j] + dp[i][j-1] - dp[i-1][j-1] + matrix[i-1][j-1];
            }
        }
    }
    
    int sumRegion(int row1, int col1, int row2, int col2) {
        return dp[row2+1][col2+1] - dp[row2+1][col1] - dp[row1][col2+1] + dp[row1][col1];
    }
private:
    vector<vector<int>> dp;
};

Java

class NumMatrix {

    public NumMatrix(int[][] matrix) {
        if(matrix.length == 0 || matrix == null)
            return;
        int m = matrix.length;
        int n = matrix[0].length;
        dp = new int[m+1][n+1];
        for(int i = 1; i <= m; ++i){
            for(int j = 1; j <= n; ++j){
                dp[i][j] = dp[i-1][j] + dp[i][j-1] - dp[i-1][j-1] + matrix[i-1][j-1];
            }
        }
        
    }
    
    public int sumRegion(int row1, int col1, int row2, int col2) {
        return dp[row2+1][col2+1] - dp[row2+1][col1] - dp[row1][col2+1] + dp[row1][col1];
    }
    private int[][] dp;
}
相關文章
相關標籤/搜索