力扣-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];
    }
};

 

posted @ 2020-07-19 15:25  Peterxiazhen  阅读(163)  评论(0编辑  收藏  举报