【LeetCode】不同路径 [M](数学)

62. 不同路径 - 力扣(LeetCode)

一、题目

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

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

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

示例 1:

【LeetCode】不同路径 [M](数学)_第1张图片

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

示例 2:
输入:m = 3, n = 2
输出:3
解释:
从左上角开始,总共有 3 条路径可以到达右下角。
1. 向右 -> 向下 -> 向下
2. 向下 -> 向下 -> 向右
3. 向下 -> 向右 -> 向下

示例 3:

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

提示:

  • 1 <= m, n <= 100
  • 题目数据保证答案小于等于 2 * 109

二、代码

class Solution {
    // m 行
	// n 列
	// 下:m-1
	// 右:n-1
    public int uniquePaths(int m, int n) {
        // 下面这两个数举一个具体例子就能想出来是怎么算的
        // 向右一共需要走多少步
        int right = n - 1;
        // 从左上角到右下角一共需要走多少步
        int all = m + n - 2;
        
        // 求排列组合公式中的分子,为了避免溢出,这里用long
        long o1 = 1;
        // 求排列组合公式中的分母
        long o2 = 1;
        // 我们通过举一个具体的例子化简就可以知道,公式中分子是从right+1开始累乘的
        // 分母是从1开始累乘的,并且o1乘进去的个数 一定等于o2乘进去的个数
        // 计算C(right, all)
        for (int i = 1, j = right + 1; j <= all; i++, j++) {
            // 计算分子
            o1 *= j;
            // 计算坟墓
            o2 *= i;
            
            // 在计算阶乘的过程中要一直进行约分化简,因为分子是有可能溢出的
            // 得到o1和o2的最大公约数
            long gcd = gcd(o1, o2);
            // o1和o2同时除以他们的最大公约数,就相当于分子和分母进行约分
            o1 /= gcd;
            o2 /= gcd;
        }

        // 最后分母o2一定会被约分成1,所以最终返回分子o1就是排列组合公式的答案。注意要转换为int
        // 这里其实返回(int)(o1 / o2)也是对的
        return (int)o1;
    }

    // 辗转相除法求a和b的最大公约数
    public long gcd(long a, long b) {
        if (b == 0) {
            return a;
        } else {
            return gcd(b, a % b);
        }
    }
}

三、解题思路 

从左上角到右下加,假设整体最多往右5步,往下4步,一共9步。

其实就相当于求94。这样就会把所有横着走和竖着走的排列组合全都求出来了。

小心溢出,有可能不溢出,但是X!可能溢出。所以在用公式求时,要注意阶乘不溢出。 

你可能感兴趣的:(LeetCode,算法,leetcode,算法,数学,排列组合,Java)