(java) leetcode 64.最小路径和

(java) leetcode 64.最小路径和_第1张图片

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

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

题目理解:

首先这是一个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

当做第三层。
(java) leetcode 64.最小路径和_第2张图片

然后我们假设一种环境,假设我们要从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];
    }
}

你可能感兴趣的:(leetcode)