【每日一题】动态规划之矩阵路径 --64. 最小路径和

题目

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

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

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

之前没有做过这个类型的题目,还是参考的力扣官方的思路。

思路一

创建二维数组dp,dp的每一个位置表示从当前位置到达右下角的路径和。
从右下角开始遍历整个二维数组:

  • 如果是最后一行,则dp等于当前网格数字加右边格子的dp加当前网格数字;
  • 如果是最后一列,则dp等于当前网格数字加下一格的dp加当前网格数字;
  • 如果是中间的格子,则dp等于右边或下边中较小的一个dp加当前网格数字。

代码一

class Solution {
    public int minPathSum(int[][] grid) {
        int[][] dp = new int[grid.length][grid[0].length];
        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) {
                    dp[i][j] = grid[i][j] + dp[i][j + 1];
                } else if (i != grid.length - 1 && j == grid[0].length - 1) {
                    dp[i][j] = grid[i][j] + dp[i + 1][j];
                } else if (i != grid.length - 1 && j != grid[0].length - 1) {
                    dp[i][j] = grid[i][j] +Math.min(dp[i + 1][j], dp[i][j + 1]);
                } else {
                    dp[i][j] = grid[i][j];
                }
            }
        }
        return dp[0][0];
    }
}

思路二

上述方法的时间复杂度是O(NM).空间复杂度是O(MN).因为开辟了一个和原数组同样大小的dp数组。那么这里可以优化的一个地方就是,可以把dp数字压缩成为一行。因为遍历的时候是从右下角开始,向左遍历完一行,再遍历上一行。所以我们再计算某一行网格对应的dp时,可以直接在原dp的基础上更改。原dp表示下一行,更新后的值代表当前行。

代码二

class Solution {
    public int minPathSum(int[][] grid) {
        int[] dp = new int[grid[0].length];
        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) {
                    dp[j] = grid[i][j] + dp[j + 1];
                } else if (i != grid.length - 1 && j == grid[0].length - 1) {
                    dp[j] = grid[i][j] + dp[j];
                } else if (i != grid.length - 1 && j != grid[0].length - 1) {
                    dp[j] = grid[i][j] +Math.min(dp[j], dp[j + 1]);
                } else {
                    dp[j] = grid[i][j];
                }
            }
        }
        return dp[0];
    }
}

one more thing

其实官方还提供了第三种空间复杂度更小的做法,即将dp数组存储到原数组上。以实现空间复杂度O(1),但是个人感觉这种方式不是很好,因为把原本的数据擦除了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值