Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/366.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 试图解决Leetcode唯一路径问题时,数字太大_Java - Fatal编程技术网

Java 试图解决Leetcode唯一路径问题时,数字太大

Java 试图解决Leetcode唯一路径问题时,数字太大,java,Java,我正试图从LeetCode解决这个问题。基本上,问题是给你一个m×n的网格,你必须计算从左上角到右下角的路径数,同时只向下或向右 我在做数学方法,这很复杂,但基本公式是: m-1+n-1选择minm-1,n-1,n选择r的公式是n!/r!*n-r 这种方法工作得很好,但最终阶乘超过了整数限制,所以它变成了负数。接下来我试着把所有的东西都改成long,但是数字又变得太大太长了。我如何简化数字,使其保持在限制之下?这是我的密码: public int uniquePaths(int m, int n

我正试图从LeetCode解决这个问题。基本上,问题是给你一个m×n的网格,你必须计算从左上角到右下角的路径数,同时只向下或向右

我在做数学方法,这很复杂,但基本公式是:

m-1+n-1选择minm-1,n-1,n选择r的公式是n!/r!*n-r

这种方法工作得很好,但最终阶乘超过了整数限制,所以它变成了负数。接下来我试着把所有的东西都改成long,但是数字又变得太大太长了。我如何简化数字,使其保持在限制之下?这是我的密码:

public int uniquePaths(int m, int n) { // The method being called
    return (int) (m == 1 || n == 1 ? 1 : choose((m - 1) + (n - 1), Math.min(m - 1, n - 1)));
}

private long choose(long n, long r) { // Calculated n choose r
    return fact(n) / (fact(r) * fact(n - r));
}

private long fact(long n) { // Calculates factorial of n
    return n == 1 ? 1 : n * fact(n - 1);
}

我知道可以简化它,因为答案是一个整数,所以数字应该很容易落在Long.MAX_值下。

好的,我知道了。我需要做的是抵消分母中较大的数字。如果r大于n-r,则公式如下:

n*n-1*n-2…*r+1/n-r

如果n-r大于r,公式如下:

n*n-1*n-2…*n-r+1/r

这使得分母中较大的数字更小,n!也更小。下面是我最后的代码:

public int uniquePaths(int m, int n) { // Method being called
    return (int) (m == 1 || n == 1 ? 1 : choose((m - 1) + (n - 1), Math.min(m - 1, n - 1)));
}

private long choose(long n, long r) { // Calculates n choose r
    return r > n - r ? fact(n, r) / fact(n - r) : fact(n, n - r) / fact(r);
}

private long fact(long n) { // Calculates n!
    return n == 1 ? 1 : n * fact(n - 1);
}

private long fact(long n, long lower) { // Calculates n! with lower bound of lower; that is n * n-1 * n-2 ... * lower+1.
    return n == lower ? 1 : n * fact(n - 1, lower);
}

在这里,在更新代码以使用java的BigInteger类之后,它被接受了

import java.math.BigInteger; 

class Solution {
    public int uniquePaths(int m, int n) { // The method being called
        BigInteger mB = BigInteger.valueOf(m);
        BigInteger nB = BigInteger.valueOf(n);
        BigInteger ans =  
                (mB.equals(BigInteger.ONE) || nB.equals(BigInteger.ONE) ? 
                BigInteger.ONE :
                choose(mB.subtract(BigInteger.ONE).add(nB.subtract(BigInteger.ONE)), 
                  mB.subtract(BigInteger.ONE).min(nB.subtract(BigInteger.ONE))));

        return ans.intValue();
    }

    private BigInteger choose(BigInteger n, BigInteger r) { // Calculated n choose r
        return fact(n).divide((fact(r).multiply(fact(n.subtract(r)))));
    }

    private BigInteger fact(BigInteger n) { // Calculates factorial of n
        return n.equals(BigInteger.ONE) ? 
            BigInteger.ONE : 
            n.multiply(fact(n.subtract(BigInteger.ONE)));
    }
}

提示:为了计算a,实际上不需要计算和除以a和b的阶乘!/Ba!/b!=a*a-1*a-2*…*a-b+1。别忘了a/bc=a/b*b/c,所以n!/Rn-r!现在变成n/r!*n/n-r!。m或n的最大值可以是100。100的阶乘!长度为158位。你甚至在计算一个更大的数字。没有int,long数据类型将能够保存这种类型的巨大数字。您可以像使用java一样使用java的BigInteger类。谢谢!我以前从未听说过BigInteger,我可能应该更多地使用它。然而,我发现的问题是它太慢了。在提交LeetCode时,我在运行时只获得了11%。有没有什么方法可以加快它的速度,或者它只是BigInteger的一个影响?