题目
给定一个包含非负整数的 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),但是个人感觉这种方式不是很好,因为把原本的数据擦除了。
最后
以上就是长情毛巾最近收集整理的关于【每日一题】动态规划之矩阵路径 --64. 最小路径和的全部内容,更多相关【每日一题】动态规划之矩阵路径内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复