2020-12-9 不同路径

题目


解题思路

法一:暴力回溯

看到题目给的示意图(一个迷宫),首先想到的就是回溯法,使用一个变量count来记录路径的条数,一旦找到一条路径count便加一,详情看代码。

class Solution {
public:
    int uniquePaths(int m, int n) {
        int count = 0;
        int a = 1, b = 1;	// 初始位置为(1,1)
        findPathCount(count, a, b, m, n);
        return count;
    }

    void findPathCount(int &count, int a, int b, int m, int n){
        if (a > m || b > n)	// 超出迷宫的范围便直接退出
            return ;
            
        if (a == m && b == n){	// 到达终点count加1
            count++;
            return ;
        }
		
        findPathCount(count, a+1, b, m, n);	// 往下走&往右走
        findPathCount(count, a, b+1, m, n);
    }
};

由于该方法时间复杂度过高,提交后未能通过。

法二:动态规划

经分析,对于迷宫中除了上边界与左边界的任一格(left(i,j ight)),到达该格可能的路径条数(dp[i][j]=dp[i-1][j]+dp[i][j-1]) ,而从起点出发到达上边界或左边界的任意一格的路径数量均能为1,因为机器人只能往下走或往右走。因此可使用动态规划来解决该问题。详情看代码。

class Solution {
public:
    int uniquePaths(int m, int n) {
        long long dp[m][n];
		
        for (int i = 0; i < m; i++)   dp[i][0] = 1;
        for (int i = 0; i < n; i++)   dp[0][i] = 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];
    }
};

时间复杂度:(O(mn))
空间复杂度:(O(mn))

法三:组合数学

从左上角到右下角的过程中,我们需要向右移动n-1次,向下移动m-1次,共移动m+n-2次。因此路径的总数,就等于从m+n-2次移动中选择m-1次向下移动的方案数,即组合数:

[C_{m+n-2}^{m-1}= binom{m+n-2}{m-1}=frac{(m+n-2)(m+n-3)...n}{(m-1)!}=frac{(m+n-2)!}{(m-1)!(n-1)!} ]

两种解法:

  • 直接调用组合数的API;
  • 自己写代码计算;
class Solution {
public:
    int uniquePaths(int m, int n) {
        long long ans = 1;
        for (int x = n, y = 1; y < m; ++x, ++y) {
            ans = ans * x / y;
        }
        return ans;
    }
};

提交结果

CS专业在读,热爱编程。
专业之外,喜欢阅读,尤爱哲学、金庸、马尔克斯。
原文地址:https://www.cnblogs.com/jmhwsrr/p/14110769.html