LeetCode/solutions/62. Unique Paths.md
2019-02-18 22:55:14 +08:00

95 lines
3.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# [62. Unique Paths](https://leetcode.com/problems/unique-paths/)
# 思路
## 思路一
### 常规版
题目要求从网格矩形的左上角移动到右下角共有多少可能的路径,一次移动只能向右或向下。
就是一个简单的递归,设置一个大小为`mxn`的数组dp初始值全为1, dp[i][j]代表从左上角到达位置第i行第j列的路径数
则根据题意可知`dp[i][j] = dp[i - 1][j] + dp[i][j - 1]`。最终的返回结果就是dp[m-1][n-1]。
时间复杂度O(mn)空间复杂度O(mn)
### 空间改进版1
思路一的空间还有改进空间因为每次计算dp[i][j]时只用到了`dp[i - 1][j]`和`dp[i][j - 1]`即每次更新只用到了dp的两行。所以我们没必要开那么大一个二维数组而只用开辟两个打消我m的一维数组cur和pre就行了分别代表当前行和前一行。然后将思路一中的`dp[i][j] = dp[i-1][j] + dp[i][j-1]` 改成`cur[i] = cur[i - 1] + pre[i]`即可每轮循环后要对调指针pre和cur以更新pre具体见代码
时间复杂度O(mn)空间复杂度O(m)
### 空间改进版2
仔细分析空间改进版1可知数组pre也是多余的只需将`cur[i] = cur[i - 1] + pre[i]`改成`cur[i] += cur[i - 1]`即可。此时将进一步节约空间。
时间复杂度O(mn)空间复杂度O(m)
## 思路二
这题就是之前高中做过的一个数学题。考虑mxn的网格机器人要想到达目的地必须一共向下走m-1步、向右走n-1步顺序不限。
所以这题转换成一个排列组合题: 有两种球分别m-1、n-1个将这些球排成一排一共有多少种排法很明显答案是(m+n-2)!/[(m-1)!(n-1)!]种(即先进行全排列再消序)。
时间复杂度O(min(m, n)), 空间复杂度O(1)
# C++
## 思路一
### 常规版
``` C++
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];
}
};
```
### 空间改进版1
```
class Solution {
public:
int uniquePaths(int m, int n) {
if (m > n) return uniquePaths(n, m);
vector<int> pre(m, 1);
vector<int> cur(m, 1);
for (int j = 1; j < n; j++) {
for (int i = 1; i < m; i++)
cur[i] = cur[i - 1] + pre[i];
swap(pre, cur);
// pre已被更新, 此时cur中的数据为无用的
}
return pre[m - 1];
}
};
```
### 空间改进版2
```
class Solution {
public:
int uniquePaths(int m, int 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];
}
};
```
## 思路二
``` C++
class Solution {
public:
int uniquePaths(int m, int n) {
if(m == 1 || n == 1) return 1;
long long res = 1, tmp = 1;
if(m < n){ // 保证m > n, 否则可能会溢出
int mbk = m;
m = n;
n = mbk;
}
for(int i = m; i <= m + n - 2; i++) res *= i; // 计算 (m + n - 2)! / (m - 1)!
for(int i = 2; i <= n - 1; i++) tmp *= i; // 计算 (n-1)!
res /= tmp;
return (int)res;
}
};
```