力扣-62-不同路径
方法一:题目分析:起点为$\left ( 0,0 \right )$,重点为$\left (m - 1,n-1 \right )$。因为机器人智能向下或者向右移动一个单元。一共需要移动$m + n - 2$步,其中向下移动$m - 1$步,向右移动$n - 1$步,向下/向右的顺序可以任意组合。所以起点到终点共有$C_{m + n-2}^{n-1}$或者$C_{m + n-2}^{m-1}$种不同的路径。
求解组合数常用的性质如下:
- $C_{n}^{0}=C_{n}^{n}=1$
- $C_{n}^{k}=C_{n}^{n-k}$
- $C_{n+1}^{k+1}=C_{n}^{k+1}+C_{n}^{k}$ 注:可以理解为,要么选第一个数,要么不选第一个数
- $C_{n}^{k+1}=C_{n}^{k}\times \frac{ n-k }{k+1}$ 注:可以根据组合数的定义验证
根据性质3,我们可以用递推的方式求解组合数,如下
memset(C, 0, sizeof(C)); for(int i = 0; i <= n; i++){ C[i][0] = 1; for(int j = 1; j <= i; j++) C[i][j] = C[i - 1][j] + C[i - 1][j - 1]; }
这个方法的时间复杂度为$O\left ( n^{2} \right )$
根据性质4,我们可以用等式4求解组合数
C[0] = 1; for(int i = 1; i <= n; i++){ C[i] = C[i - 1] * (n - i + 1)/i; }
应该先乘后除,因为直接除可能结果不是整数。而先乘的话可能会以爆long long,可以先约分。
#include <algorithm> #include <string> typedef long long ll; ll ans[20005]; class Solution { public: int uniquePaths(int m, int n) { int k = min(m - 1, n - 1); memset(ans, 0, sizeof(ans)); ans[0] = 1; for(int i = 1; i <= k; i++) ans[i] = ans[i - 1] * (m + n - 2 - i + 1) / i; return ans[k]; } };
方法二:动态规划的思想
令$dp\left [ i \right ]\left [ j \right ]$表示到达$\left ( i,j \right )$位置时的不同路径的数目。那么考虑到机器人只能向下或向右,所以:
$dp\left [ i \right ]\left [ j \right ]=dp\left [ i-1 \right ]\left [ j \right ]+dp\left [ i \right ]\left [ j-1 \right ]$
注意,第一行(列)只能由起点直接到达,也就是$dp\left [ i \right ]\left [ 0 \right ]=dp\left [ 0 \right ]\left [ j \right ]=1$
#include <algorithm> #include <string> int dp[105][105]; class Solution { public: int uniquePaths(int m, int n) { memset(dp, 0, sizeof(dp)); for(int i = 0; i < m; i++) dp[i][0] = 1; for(int j = 0; j < n; j++) dp[0][j] = 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]; } };
作者:Ryanjie
出处:http://www.cnblogs.com/ryanjan/
本文版权归作者和博客园所有,欢迎转载。转载请在留言板处留言给我,且在文章标明原文链接,谢谢!
如果您觉得本篇博文对您有所收获,觉得我还算用心,请点击右下角的 [推荐],谢谢!