(java) leetcode 64.最小路径和

在这里插入图片描述

此题是一个很经典的动态规划题目了,思路不难,但是确实很体现动态规划的思想。

然后我们就来分析一下这个题目。

题目理解:

首先这是一个m*n的矩阵,我们需要寻找一条最短路径,从左上到右下,我们不能单纯考虑向右一个单位和向下一个单位哪个更短,这就变成贪心了,所以显然是行不通的,除此之外,还要考虑m和n范围的问题,不能ArraysOutOfException,所以我们可以有这样的一种思路。

题目思路

我们用题目中给的这个矩阵作为案例。假设路径和为dp[m][n]

我们从左上角的1出发,不管你怎么走,都一定会经过第一行或者第一列。

那么我们为何不把第一行或者第一列的数字和先提前算出来去比较呢。也就是dp[i][0] (0≤i≤m)和dp[0][i] (0≤i≤n)

算出来之后,我们又知道,不管怎么走,肯定都会经过dp[i][j] (0≤i≤m)(0≤j≤n)或者dp[j][i] (0≤j≤m)(0≤i≤n),那么,我们刚才计算出的第一行或者第一列的数字和就有用了。

然后我画一张图:

我们把
1 3 1
1
4

当做第一层,把

5 1
2

当做第二层,把

1

当做第三层。
在这里插入图片描述

然后我们假设一种环境,假设我们要从grid[0][0]到达grid[1][1],那么就一定会有两条路,没错,从→↓或者从↓→,但是路径和肯定是不一样的,但我们仔细分析一下,这两路不管怎么走,我们的dp[1][1]都要加上grid[1][1],只要考虑两种路径哪个更短就行了。

其实方法是很简单的,就是Math.min(dp[1-1][1],dp[1][1-1]),然后我们就能知道到grid[1][1]用哪条路径最短了,只不过,比完之后,还需要加上grid[1][1]。

以此类推,我们可以列出方程:

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

然后再排除一些无聊的特例就行了。

我的代码是:

class Solution {
    public int minPathSum(int[][] grid) {
        int m = grid.length;
        int n = grid[0].length;
        
        int sum = 0;
        
        if(m<1||n<1) return 0;
        if(m == 1 ){
            for(int i = 0 ; i < n ; i++){
                sum = sum + grid[0][i];
            }
            return sum;
        }
        if(n == 1 ){
            for(int i = 0 ; i < m ; i++){
                sum = sum + grid[i][0];
            }
            return sum;
        }
        
        int [][]dp = new int[m][n];
        dp[0][0] = grid[0][0];
        
        for(int k = 1 ; k < m ; k++){
            dp[k][0] = grid[k][0] + dp[k-1][0];
        }
        
        for(int l = 1; l < n ; l++){
            dp[0][l] = grid[0][l] + dp[0][l-1];
        }
        
        for(int k = 1; k<m ; k++){
            for(int l = 1; l<n ; l++){
                dp[k][l] = grid[k][l] + Math.min(dp[k-1][l],dp[k][l-1]);
            }
        }
        return dp[m-1][n-1];
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值