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?
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];
}
};

本文探讨了LeetCode上的经典动态规划问题“不同路径”,提供了多种C++实现方式,包括简洁的DP初始化、直观的两维数组实现、以及优化的空间复杂度解决方案。

122

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



