LeetCode 64. Minimum Path Sum

问题描述

这里写图片描述

问题分析

  • 该题和 LeetCode 120. Triangle 一样,是用动态规划求解最值问题,求解路径最小和问题。只不过120是三角形,可以说比该题稍微麻烦一点吧。
  • 同样是先从递归入手,然后到动态规划,然后是动态规划的空间优化。
  • 关于空间优化,因为dp[i][j] 只依赖于 dp[i + 1][j]dp[i][j + 1],那么同样可用一个数组滚动更新,来取代二维数组,只是要注意,是从右向左更新!!!注意顺序!!!

经验教训

  • 注意动态规划时如何设计矩阵大小问题,该题也可以让dp再多加一行,多加一列,值全是 Integer.MAX_VALUE,然后更新即可。

代码实现

  • 递归(TLE)
    public int minPathSum(int[][] grid) {
        if (grid == null || grid.length == 0 || grid[0] == null || grid[0].length == 0) {
            return 0;
        }
        //从[0,0]出发
        return getMinPathSum(grid, 0, 0);
    }

    //表示从[i,j]出发,到右下角的最短路径
    public int getMinPathSum (int[][] grid, int i, int j) {
        //已到右下角
        if (i == grid.length - 1 && j == grid[0].length - 1) {
            return grid[i][j];
        }
        //出界,设为最大值,也就相当于把该选择置为无效
        if (i == grid.length || j == grid[0].length) {
            return Integer.MAX_VALUE;
        }
        //递归
        return grid[i][j] + Math.min(getMinPathSum(grid, i + 1, j), getMinPathSum(grid, i, j + 1));
    }
  • 动态规划
    public int minPathSum(int[][] grid) {
        if (grid == null || grid.length == 0 || grid[0] == null || grid[0].length == 0) {
            return 0;
        }
        int row = grid.length;
        int col = grid[0].length;
        //dp[i][j] 表示从[i,j]出发到右下角的最小路径和
        int[][] dp = new int[row][col];
        //初始化最后一行
        dp[row - 1][col - 1] = grid[row - 1][col - 1];
        for(int j = col - 2; j >= 0; --j) {
            dp[row - 1][j] = dp[row - 1][j + 1] + grid[row - 1][j];
        }
        //从下到上,从右到左填写该二维表
        for (int i = row - 2; i >= 0; --i) {
            //初始化该列最后一个元素
            dp[i][col - 1] = dp[i + 1][col - 1] + grid[i][col - 1];
            for (int j = col - 2; j >= 0; --j) {
                dp[i][j] = grid[i][j] + Math.min(dp[i + 1][j], dp[i][j + 1]);
            }
        }
        return dp[0][0];
    }
  • 动态规划空间优化
    public int minPathSum(int[][] grid) {
        if (grid == null || grid.length == 0 || grid[0] == null || grid[0].length == 0) {
            return 0;
        }
        int row = grid.length;
        int col = grid[0].length;
        int[] dp = new int[col];
        dp[col - 1] = grid[row - 1][col - 1];
        for(int j = col - 2; j >= 0; --j) {
            dp[j] = dp[j + 1] + grid[row - 1][j];
        }
        for (int i = row - 2; i >= 0; --i) {
            //先单独处理最后一个
            dp[col - 1] = dp[col - 1] + grid[i][col - 1];
            //从右向左更新
            for (int j = col - 2; j >= 0; --j) {
                dp[j] = grid[i][j] + Math.min(dp[j], dp[j + 1]);
            }

        }
        return dp[0];
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值