64 - 动态规划
Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path.
Note: You can only move either down or right at any point in time.
Example:
Input:
[
[1,3,1],
[1,5,1],
[4,2,1]
]
Output: 7
Explanation: Because the path 1→3→1→1→1 minimizes the sum.
代码如下: 思路见注释
class Solution {
public:
int minPathSum(vector<vector<int> >& grid) {
int m = grid.size(), n = grid[0].size();
vector<vector<int> > dp(m, vector<int>(n)); // m rows, n cols
// Recursive formula: dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + grid[i][j]
// The initial value:
// dp[0][0] = grid[0][0]
// dp[0][j > 0] = dp[0][j-1] + grid[i][j]
// dp[i > 0][j] = dp[i-1][0] + grid[i][j]
// Complexity: Time: O(m*n), Space: O(m * n)
for (int i = 0; i < m; ++i){
for (int j = 0; j < n; ++j){
if (i == 0) { // 初始条件
if (j == 0) {
dp[i][j] = grid[i][j];
}
else {
dp[i][j] = dp[i][j - 1] + grid[i][j];
}
}
else if (j == 0) {
dp[i][j] = dp[i - 1][j] + grid[i][j];
}
else // 递推
dp[i][j] = min(dp[i][j - 1], dp[i - 1][j]) + grid[i][j];
}
}
return dp[m-1][n-1];
}
};
分析:初级方法时间复杂度和空间复杂度都太高,怎么优化?
可看出:
dp[i][j]只与dp[i-1][j],dp[i][j-1]有关;- 对每一个
i,正向循环j;dp[j-1]不断更新,dp[j]还是旧的dp[j] = min(dp[j-1], dp[j]) + grid[i][j]这样省掉了第一维
其实就是我们不需要维护完整的m*n矩阵。维护两列就足够了,现在我们有了以下代码。
int m = grid.size(), n = grid[0].size();
vector<int> dp(n);
for (int i = 0; i < m; ++i){
for (int j = 0; j < n; ++j){
if (i == 0) {
if (j == 0) {
dp[j] = grid[i][j];
}
else {
dp[j] = dp[j - 1] + grid[i][j];
}
}
else if (j == 0) {
dp[j] = dp[j] + grid[i][j];
}
else {
dp[j] = min(dp[j - 1], dp[j]) + grid[i][j];
}
}
}
return dp[n - 1];
```
待续....
本文介绍了一个典型的动态规划问题——寻找从二维网格左上角到右下角的路径,使得路径上的数字之和最小。提供了两种解决方案及其代码实现,并讨论了如何优化空间复杂度。
507

被折叠的 条评论
为什么被折叠?



