64. 最小路径和

题目描述

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

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

示例:

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

暴力递归思路

1.我们可以将每个位置向右和向下的结果都求出来,然后每次都选择最小的加起来即可。

Java代码实现

    public int minPathSum(int[][] grid) {
        return minPathSum(grid,0,0);
    }

    private int minPathSum(int[][] grid,int i,int j,int[][] memory) {
        if(i == grid.length)
            return Integer.MAX_VALUE-grid[i-1][j];
        if(j == grid[0].length)
            return Integer.MAX_VALUE-grid[i][j-1];
        if(i == grid.length-1 && j == grid[0].length-1)
            return grid[i][j];
        int path1 = grid[i][j]+minPathSum(grid,i+1,j,memory);
        int path2 = grid[i][j]+minPathSum(grid,i,j+1,memory);
        int curPath = Math.min(path1,path2);
        return curPath;
    }

备忘录方法

1.我们可以发现暴力法会将同一个位置的答案计算多次,所以我们可以将计算过的答案存储起来,如果发现该位置的答案已经算好了,就不用再递归求结果了,可以大幅度减少递归的次数。

Java代码实现

    public int minPathSum(int[][] grid) {
        int[][] memory = new int[grid.length][grid[0].length];
        return minPathSum(grid,0,0,memory);
    }

    private int minPathSum(int[][] grid,int i,int j,int[][] memory) {
        if(i == grid.length)
            return Integer.MAX_VALUE-grid[i-1][j];
        if(j == grid[0].length)
            return Integer.MAX_VALUE-grid[i][j-1];
        if(i == grid.length-1 && j == grid[0].length-1)
            return grid[i][j];
        if(memory[i][j] != 0)
            return memory[i][j];
        int path1 = grid[i][j]+minPathSum(grid,i+1,j,memory);
        int path2 = grid[i][j]+minPathSum(grid,i,j+1,memory);
        int curPath = Math.min(path1,path2);
        memory[i][j] = curPath;
        return curPath;
    }

动态规划

1.我们可以通过以上两种方法可以总结出状态转移方程为:dp(i,j)=grid(i,j)+min(dp(i+1,j),dp(i,j+1))
2.我们设置一个二维数组存储dp的结果,然后将dp[0][0]作为结果返回即可。

Java代码实现

    public int minPathSum(int[][] grid) {
        int[][] res = new int[grid.length+1][grid[0].length+1];
        for (int i = grid.length-1; i >= 0 ; i--) {
            for (int j = grid[0].length - 1; j >= 0; j--) {
                if (i == grid.length - 1 && j == grid[0].length - 1) {
                    res[i][j] = grid[i][j];
                    continue;
                }
                //如果是最后一行
                if (i == grid.length - 1) {
                    res[i][j] = grid[i][j] + res[i][j + 1];
                    continue;
                }
                //如果是最后一列
                if (j == grid[0].length - 1) {
                    res[i][j] = grid[i][j] + res[i + 1][j];
                    continue;
                }
                res[i][j] = Math.min(grid[i][j] + res[i][j + 1], grid[i][j] + res[i + 1][j]);
            }
        }
        return res[0][0];
    }

你可能感兴趣的:(64. 最小路径和)