【LeetCode】64.最小路径和

85 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第6天,点击查看活动详情

题目

给定一个包含非负整数的 *m* x *n* 网格 grid ,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。

**说明:**每次只能向下或者向右移动一步。

示例 1

img

输入:grid = [[1,3,1],[1,5,1],[4,2,1]]
输出:7
解释:因为路径 13111 的总和最小。

示例 2

输入:grid = [[1,2,3],[4,5,6]]
输出:12

提示

  • m == grid.length
  • n == grid[i].length
  • 1 <= m, n <= 200
  • 0 <= grid[i][j] <= 100

题解

思路

明确 base case:显然是当 i = 0 and j = 0,最小路径和直接是 grid[0][0]

明确「状态」:原问题和子问题中会发生变化的变量。grid[0..i][0..j]会不断地向 base case 靠近,所以唯一的「状态」就是矩阵 grid[0..i][0..j]

明确「选择」:导致「状态」产生变化的行为。矩阵 grid[0..i][0..j] 为什么变化呢?因为在选择不同的方向,每选择一种方向,矩阵就会收缩。所以说「上方 or 左方」就是「选择」(每次都可在选择任意一种方向)

明确 dp 数组/函数的定义。这里采用自底向上的解法,所以会有一个递推的 dp 数组,一般来说数组的下标就是状态转移中会变化的量,即:「状态」;数组的值就是 grid[0..i][0..j] 的最小路径和

代码

public int minPathSum(int[][] grid) {
    int m = grid.length;
    int n = grid[0].length;
    int[][] dp = new int[m + 1][n + 1];
    // 初始化 dp[]
    for (int i = 0; i < dp.length; i++) dp[i][0] = Integer.MAX_VALUE;
    for (int j = 0; j < dp[0].length; j++) dp[0][j] = Integer.MAX_VALUE;
    dp[0][1] = 0;
    dp[1][0] = 0;
    
    for (int i = 1; i < dp.length; i++) {
        for (int j = 1; j < dp[0].length; j++) {
            dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + grid[i - 1][j - 1];
        }
    }
    return dp[m][n];
}

结语

业精于勤,荒于嬉;行成于思,毁于随。