LeetCode 62.不同路径

88 阅读2分钟

「这是我参与2022首次更文挑战的第24天,活动详情查看:2022首次更文挑战」。

题目:给定一个m*n的网格,起点在左上角,终点在右下角,要求找出所有可能的从起点到终点的路径。

解题思路

刚好去年学过组合数学,还是我导师教的~~本题就是组合数学组合数的题目,机器人从起点到终点,必然需要走的格子数为m+n-2个,无非就是向下走和向右走,并且向下走和向右走的格子数是确定的,向下走个数为m-1,向右走个数为n-1,因此无论怎么走,其最终路径数为Cm+n2m1C_{m+n-2}^{m-1},因此只需计算此阶乘式即可,代码如下:

public int uniquePaths(int m, int n) {
        if(m==1||n==1) return 1;
        return (int)(factorial(m+n-2) / factorial(m-1) / factorial(n-1));
    }

    public long factorial(int n){
        if(n==0) return 1;
        return n*factorial(n-1);
    }

上述代码无法通过,存在数的越界问题,可能是自己写的计算阶乘局限性比较大。既然直接计算阶乘不行,那么是否可以尝试换一个思路,如下阶乘:

Cm+n2m1C_{m+n-2}^{m-1},其直接计算方式为(m+n2)!(m1)!(n1)!\frac{(m+n-2)!}{(m-1)!(n-1)!},首先需要计算(m+n2)!(m+n-2)!之后还要计算m1m-1n1n-1的阶乘,此时存在重复计算,实际上只需要计算从mm开始到m+n2m+n-2的数相乘即可再除以n1n-1的阶乘,换种思路计算:

是否可以从mm开始一直累加,累加到m+n2m+n-2,而nn11累加,累加到n1n-1,每次累加计算一部分,例如52!10!42!\frac{52!}{10!42!}, 首先计算42*43/1,以此类推,从而得到最终解,最终代码如下:

public int uniquePaths(int m, int n) {
        long result = 1;
        for(int x=m, y=1;y<n;x++, y++){
            result = result*x / y;
        }
        return (int)result;
    }

上述代码最终耗时0ms,击败百分之百Java提交用户,时间复杂度为O(N)O(N),空间复杂度为O(1)O(1)

最后

本题虽然是组合数学的一个知识点,但若想代码写出来则还需要更多的思考,比较亮眼的就是计算组合数的一种新的方式。