9.最小路径和(medium)

1.题目链接:

https://leetcode.cn/problems/minimum-path-sum/description/https://leetcode.cn/problems/minimum-path-sum/description/

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

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

示例 1:​

     输入:grid = [[1,3,1],[1,5,1],[4,2,1]]​
     输出:7​
     解释:因为路径 1→3→1→1→1 的总和最小。​
3. 解法(动态规划):
算法思路:
像这种表格形式的动态规划,是非常容易得到「状态表示」以及「状态转移方程」的,可以归结到「不同路径」一类的题里面。

1. 状态表示:
        对于这种路径类的问题,我们的状态表示一般有两种形式:

i.

[i, j]  位置出发,巴拉巴拉;​

  ii. 从起始位置出发,到达 [i, j]  位置,巴拉巴拉。​这里选择第二种定义状态表示的方式:
dp[i][j]  表示:到达 [i, j]  位置处,最小路径和是多少。​

2. 状态转移:
        简单分析一下。如果 dp[i][j]  表示到达 到达 [i, j]  位置处的最小路径和,那么到达           [i, j]  位置之前的一小步,有两种情况:​

i.

[i - 1, j]  向下走一步,转移到 [i, j]  位置;​

ii.[i, j - 1]  向右走一步,转移到 [i, j]  位置。​
由于到 [i, j] 位置两种情况,并且我们要找的是最小路径,因此只需要这两种情况下的最小值,再加上[i, j] 位置上本身的值即可。

也就是:dp[i][j] = min(dp[i - 1][j], dp[i][j - 1]) + grid[i][j]

3. 初始化:

可以在最前面加上一个「辅助结点」,帮助我们初始化。使用这种技巧要注意两个点:i.   辅助结点里面的值要「保证后续填表是正确的」;
ii. 「下标的映射关系」。

在本题中,「添加一行」,并且「添加一列」后,所有位置的值可以初始化为无穷大,然后让 dp[0][1] = dp[1][0] = 1  即可。​

4. 填表顺序:
根据「状态转移方程」的推导来看,填表的顺序就是「从上往下」填每一行,每一行「从左往后」。

5. 返回值:
        根据「状态表示」,我们要返回的结果是 dp[m][n] 。​

Java算法代码:

class Solution {
    public int minPathSum(int[][] grid) {
        // 1.创建dp表
        // 2.初始化
        // 3.填表
        // 4.返回值
        int m = grid.length, n = grid[0].length;
        int[][] dp = new int[m+1][n+1];
        for(int j = 0; j <= n; j++) dp[0][j] = 0x3f3f3f;
        for(int i = 0; i <= m; i++) dp[i][0] = 0x3f3f3f;
        dp[0][1] = dp[1][0] = 0;

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

运行结果:

动态规划:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值