算法学习Day39不同路径

Day39不同路径

By HQWQF 2024/01/22

笔记


62.不同路径

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。

问总共有多少条不同的路径?

示例 1:

输入:m = 3, n = 7
输出:28

动态规划

对于任意一个位置,到达该位置的路径数等于到达该位置上方和左方位置的路径数之和。

边界上的位置到达路径数都是1,需要初始化。

class Solution {
public:
    int uniquePaths(int m, int n) {
        vector<vector<int>> dp(m, vector<int>(n, 0));
        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];
    }
};

组合数法

应用高中数学,我们知道到达右下角必须向下走m-1步和向右n-1步,假设总共走n步。

所以这n步里必须有k步是向下的,所以n就是组合数c m-1 m+n-2。

​分子和分母可以直接抵消一部分,所以我们将从大到小阶乘,对分子阶乘m - 1或n - 1次,剩下的都被抵消了。

公式为:

C(m+n−2,m−1)=
(m−1)!(n−1)!/(m+n−2)!

但是我们知道计算组合数里的阶乘是容易溢出的,所以需要有特殊的处理。

直观的代码,会溢出:

class Solution {
public:
    int uniquePaths(int m, int n) {
        int numerator = 1, denominator = 1;
        int count = m - 1;
        int t = m + n - 2;
        while (count--) numerator *= (t--); // 计算分子,此时分子就会溢出
        for (int i = 1; i <= m - 1; i++) denominator *= i; // 计算分母
        return numerator / denominator;
    }
};

需要在计算分子的时候,不断除以分母

class Solution {
public:
    int uniquePaths(int m, int n) {
        long long numerator = 1; // 分子
        int denominator = m - 1; // 分母,可为n-1
        int count = m - 1;//可为n-1
        int t = m + n - 2;
        while (count--) {
            numerator *= (t--);
            while (denominator != 0 && numerator % denominator == 0) {
                numerator /= denominator;
                denominator--;
            }
        }
        return numerator;
    }
};
posted @ 2024-01-22 23:41  HQWQF  阅读(19)  评论(0)    收藏  举报