题目:
题解
- 最优化问题,考虑动态规划。
- 划分子问题:
dp[i][j]
表示走到(i,j)
时的最小路径和。 - 用子问题表示原问题:则
dp[m-1][n-1]
为原问题的解。 - 将子问题用其他子问题表示:因为只能向下或向右走,则
(i,j)
可以由左边(i,j-1)
或上边(i-1,j)
移动到,dp[i][j] = min(dp[i][j-1],dp[i-1][j]) + g[i][j]
,所以只需要考虑左边和上边边界。
- 当
(i,j)
是左上角时,i=0, j=0
,则dp[i][j] = g[i][j]
。 - 当
(i,j)
在左边界,i != 0, j=0
,则当前位置只能从上边移动到,dp[i][j] = dp[i-1][j] + g[i][j]
。 - 当
(i,j)
在上边界,i = 0, j != 0
,则当前位置只能从左边移动到,dp[i][j] = dp[i][j-1] + g[i][j]
。 - 当
(i,j)
不在左/上边界,i != 0, j != 0
,则dp[i][j] = min(dp[i][j-1], dp[i-1][j]) + g[i][j]
。
代码
package leetcode.dp;
import java.util.Scanner;
public class MatrixMinPathSum {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
while(s.hasNext()) {
int m = s.nextInt();
int n = s.nextInt();
int[][] grid = new int[m][n];
for(int i=0;i<n;i++) {
for(int j=0;j<n;j++) {
grid[i][j] = s.nextInt();
}
}
System.out.println(minPathSum(grid));
}
s.close();
}
public static int minPathSum(int[][] grid) {
if(grid == null || grid.length == 0 || grid[0].length == 0) return 0;
int m = grid.length;
int n = grid[0].length;
int[][] dp = new int[m][n];
for(int i=0;i<m;i++) {
for(int j=0;j<n;j++) {
if(i == 0 && j == 0)
dp[i][j] = grid[0][0];
if(i != 0 && j == 0)
dp[i][j] = dp[i-1][j] + grid[i][j];
if(i == 0 && j != 0)
dp[i][j] = dp[i][j-1] + grid[i][j];
if(i != 0 && j != 0)
dp[i][j] = Math.min(dp[i-1][j], dp[i][j-1]) + grid[i][j];
}
}
return dp[m-1][n-1];
}
}
空间优化
- 可以直接在原grid二维数组中建立dp数组
- 复杂度:
时间复杂度 O(m*n) : 遍历整个 grid 矩阵。
空间复杂度 O(1) : 直接覆盖原矩阵,不使用额外空间。