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