62. Unique Paths**
https://leetcode.com/problems/unique-paths/
题目描述
A robot is located at the top-left corner of a m x n
grid (marked 'Start'
in the diagram below).
The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked 'Finish'
in the diagram below).
How many possible unique paths are there?
![](https://i-blog.csdnimg.cn/blog_migrate/6710b69f699f18199567f563ce9a90da.png)
Note: m
and n
will be at most 100.
Example 1:
Input: m = 3, n = 2
Output: 3
Explanation:
From the top-left corner, there are a total of 3 ways to reach the bottom-right corner:
1. Right -> Right -> Down
2. Right -> Down -> Right
3. Down -> Right -> Right
Example 2:
Input: m = 7, n = 3
Output: 28
解题思路
动态规划.
机器人在大小为 m x n
的网格的左上角, 现在它要走到网格的右下角处, 只能向右或者向下移动, 问有多少种不同的走法?
思路: 当 m = 1
或 n = 1
时, 移动到任何一个位置都只有一种走法. 现在设 dp[i][j]
为走到 (i, j)
处时的走法, 那么 d[i][j] = d[i - 1][j] + d[i][j - 1]
.
C++ 实现 1
将 dp
初始值设置为 1 会使得代码更为简洁.
class Solution {
public:
int uniquePaths(int m, int n) {
vector<vector<int>> dp(m, vector<int>(n, 1));
for (int i=1; i<m; i++) {
for (int j=1; j<n; j++) {
dp[i][j] = dp[i-1][j] + dp[i][j-1];
}
}
return dp[m-1][n-1];
}
};
C++ 实现 2
更为直观的做法.
class Solution {
public:
int uniquePaths(int m, int n) {
vector<vector<int>> dp(m, vector<int>(n, 0));
for (int j = 0; j < n; ++j)
dp[0][j] = 1;
for (int i = 0; i < m; ++i)
dp[i][0] = 1;
for (int i = 1; i < m; ++i) {
for (int j = 1; j < n; ++j) {
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
}
}
return dp[m - 1][n - 1];
}
};
C++ 实现 3
可以发现下面的代码非常简洁. 注意两点:
dp
设置为(m+1) * (n+1)
大小, 在原矩阵上方和左方分别增加了一行和一列, 那么原矩阵(0, 0)
的位置就是dp
中(1, 1)
的位置. 因此最终返回的结果是dp[m][n]
- 注意
dp
初始化为0,
并且dp[0][1]
设置为1
. 这样的好处是, 在下面的两个循环中, 就不用判断边界条件了. 比如要求dp[1][1]
(也就是到达原矩阵(0, 0)
位置时的方法), 结果就是1
.
class Solution {
public:
int uniquePaths(int m, int n) {
vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));
dp[0][1] = 1;
for (int i = 1; i <= m; ++i)
for (int j = 1; j <= n; ++j)
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
return dp[m][n];
}
};
C++ 实现 4
看看 leetcode 上关于这道题的精彩讨论:
0ms, 5-lines DP Solution in C++ with Explanations
下面的解法是在使用 dp[i][j]
的基础上, 观察到每次更新 dp
的过程中, 实际上只需要当前列 dp[...][j]
以及它前一列 dp[...][j - 1]
的值, 因此可以先用两个 vec
来降低空间复杂度, 后来又发现, 第 i
列的值实际上可以用 cur[i] += cur[i - 1];
(详情见讨论) 简化, 所以再次降低了复杂度.
class Solution {
int uniquePaths(int m, int n) {
// 下面的 if 是进一步的优化, 使得空间复杂度为 O(min(m, n))
if (m > n) return uniquePaths(n, m);
vector<int> cur(m, 1);
for (int j = 1; j < n; j++)
for (int i = 1; i < m; i++)
cur[i] += cur[i - 1];
return cur[m - 1];
}
};