LeetCode Hot100刷题——最小路径和(动态规划)

64.最小路径和

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

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

示例 1:

LeetCode Hot100刷题——最小路径和(动态规划)_第1张图片

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

示例 2:

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

提示:

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

1.解题思路:动态规划

因为每一步的选择会影响后续的路径,而本题需要找到全局最优解。动态规划通常适用于这类问题,因为它可以存储中间值,避免重复计算。

动态规划转移方程:

        假设有二维数组dp,其中dp[i][j]表示从起点(0,0)到点(i,j)的最小路径和。那么到底(i,j)有两种方式:从上面(i-1,j)下来,或者从左面(i,j-1)过来。需要选择这两种方式中路径和较小的那个,再加上当前格子的值。所有状态转移方程应该是:

        dp[i][j] = grid[i][j] + min(dp[i-1][j],dp[i][j-1])

        接下来,初始化的问题。对于第一行和第一列,因为它们只能从左边或者上边来,所以dp的第一行的每个位置的值应该是左边所有格子的累加,同理第一列是上面所有格子的累加。例如,第一行的dp[0][j] = dp[0][j-1] + grid[0][j]。类似地,第一列的dp[i][0] = dp[i-1][0] + grid[i][0]。

2.代码步骤

  • 获取网格的行数m和列数n。
  • 创建dp数组,大小和grid相同。
  • 初始化dp[0][0]为grid[0][0]。
  • 初始化第一行和第一列。
  • 遍历剩下的每个位置,填充dp数组。
  • 返回dp[m-1][n-1]。

3.实现代码

class Solution {
    public 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];
        dp[0][0] = grid[0][0];

        // 初始化第一行
        for (int j = 1; j < n; j++) {
            dp[0][j] = dp[0][j - 1] + grid[0][j];
        }

        // 初始化第一列
        for (int i = 1; i < m; i++) {
            dp[i][0] = dp[i - 1][0] + grid[i][0];
        }

        // 其他位置
        for (int i = 1; i < m; i++) {
            for (int j = 1; j < n; j++) {
                dp[i][j] = Math.min(dp[i][j - 1], dp[i - 1][j]) + grid[i][j];
            }
        }
        return dp[m - 1][n - 1];
    }
}

总结

  1. 初始化处理:首先处理第一行和第一列,累加路径和,因为它们的路径是唯一的。

  2. 动态规划填充:从第二行第二列开始,每个位置的最小路径和为当前值加上上方或左方的最小路径和。

你可能感兴趣的:(leetcode,算法,职场和发展,动态规划,java)