天天看点

算法学习之动态规划(leetcode 304. Range Sum Query 2D - Immutable)

leetcode 304. Range Sum Query 2D - Immutable

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

算法学习之动态规划(leetcode 304. Range Sum Query 2D - Immutable)

Example:

Given matrix = [
  [, , , , ],
  [, , , , ],
  [, , , , ],
  [, , , , ],
  [, , , , ]
]

sumRegion(, , , ) -> 
sumRegion(, , , ) -> 
sumRegion(, , , ) -> 
           

Note:

You may assume that the matrix does not change.

There are many calls to sumRegion function.

You may assume that row1 ≤ row2 and col1 ≤ col2.

解析:

本来自己在做的时候,直接就去遍历,发现超时,没有往动态规划这块去想,就是缺少一个明确的定义。动态规划的第一步就是要有一个明确的定义。

lc上discuss中优美的答案,首先定义一个比原矩阵大一圈的矩阵dp[m+1][n+1],便于后续边界条件的判断。

dp[i][j]的含义是在(i, j)之前,所有元素的和,不包括(i, j),那么整个矩阵的和就是dp[m+1][n+1]。

而且dp矩阵的初始化需要使用动态规划的思路。

如下图

算法学习之动态规划(leetcode 304. Range Sum Query 2D - Immutable)

显然

dp[i][j] = dp[i-1][j] + dp[i][j-1] - dp[i-1][j-1] 
           + m[i-1][j-1];
           

后续的public int sumRegion(int row1, int col1, int row2, int col2)函数可以使用几个矩阵的运算来做

算法学习之动态规划(leetcode 304. Range Sum Query 2D - Immutable)

公式为

紫色面积 = dp[row2+1][col2+1] - dp[row1][col2+1] 
                         - dp[row2+1][col1] 
                         - + dp[row1][col1];
           

具体的代码实现如下

public class NumMatrix {
    public static int[][] m;
    public static int[][] dp;

    public NumMatrix(int[][] matrix) {
        if(matrix == null || matrix.length ==  || matrix[].length == ){
            m = null;
        }
        else{
            m = new int[matrix.length][matrix[].length];
            for(int i = ; i < matrix.length; i++){
                for(int j = ; j < matrix[].length; j++){
                    m[i][j] = matrix[i][j];
                }
            }

            dp = new int[matrix.length+][matrix[].length+];
            for(int i = ; i <= matrix.length; i++){
                for(int j = ; j <= matrix[].length; j++){
                    dp[i][j] = dp[i-][j] + dp[i][j-] - dp[i-][j-] + m[i-][j-];
                }
            }
        }
    }

    public int sumRegion(int row1, int col1, int row2, int col2) {
        return dp[row2+][col2+] - dp[row1][col2+] - dp[row2+][col1] + dp[row1][col1];
    }
}

// Your NumMatrix object will be instantiated and called as such:
// NumMatrix numMatrix = new NumMatrix(matrix);
// numMatrix.sumRegion(0, 1, 2, 3);
// numMatrix.sumRegion(1, 2, 3, 4);