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];
```
待续....