英文:
Numbers Too Big While Trying To Solve Leetcode Unique Paths Problem
问题
我正在尝试解决LeetCode上的Unique Paths问题。基本上,问题是给你一个m
乘n
的网格,你需要计算从左上角到右下角的路径数量,只能向下或向右移动。
我正在使用数学方法,这个方法相当复杂,但基本公式如下:
(m - 1 + n - 1) 选择 (min(m - 1, n - 1))
,而n选择r
的公式为 n! / (r! * (n-r)!)
。
这个方法效果不错,但是最终阶乘会超过整数限制,所以会变成负数。我尝试的下一个方法是将所有内容都改为long
,但是数字对long
来说也变得太大了。我该如何简化这些数字,使其保持在限制范围内呢?以下是我的代码:
public int uniquePaths(int m, int n) { // 调用的方法
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) { // 计算 n 选择 r
return fact(n) / (fact(r) * fact(n - r));
}
private long fact(long n) { // 计算 n 的阶乘
return n == 1 ? 1 : n * fact(n - 1);
}
我知道可以简化它,因为答案是一个整数,所以数字应该很容易落在 Long.MAX_VALUE
之下。
英文:
I am trying to solve the Unique Paths problem from LeetCode. Basically, the problem is you're given an m
by n
grid, and you have to count the number of paths from the top left to the bottom right while only going down or right.
I am doing the mathematical approach, which is pretty complicated to figure out but the basic formula is this:
(m - 1 + n - 1) choose (min(m - 1, n - 1))
, and the formula for n choose r
is n! / (r! * (n-r)!)
.
This approach works well, but eventually the factorial goes past the integer limit, so it becomes negative. The next thing I tried was to change everything to long, but then again the numbers became too big for long, too. How can I simplify the numbers so it stays under the limit? Here is my code:
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);
}
I know it's possible to simplify it because the answer is an integer, so the number should easily fall under Long.MAX_VALUE
.
答案1
得分: 1
在将代码更新为使用 Java 的 BigInteger 类之后,它被接受了。
import java.math.BigInteger;
class Solution {
public int uniquePaths(int m, int n) { // 调用的方法
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) { // 计算 n 选 r
return fact(n).divide((fact(r).multiply(fact(n.subtract(r)))));
}
private BigInteger fact(BigInteger n) { // 计算 n 的阶乘
return n.equals(BigInteger.ONE) ?
BigInteger.ONE :
n.multiply(fact(n.subtract(BigInteger.ONE)));
}
}
英文:
Here after updating your code to use BigInteger class of java, it got accepted.
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)));
}
}
答案2
得分: 0
好的,以下是翻译好的部分:
好的,我明白了。我需要做的是在分母中消除较大的数。如果 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) { // 调用的方法
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) { // 计算组合数 n 选择 r
return r > n - r ? fact(n, r) / fact(n - r) : fact(n, n - r) / fact(r);
}
private long fact(long n) { // 计算阶乘 n!
return n == 1 ? 1 : n * fact(n - 1);
}
private long fact(long n, long lower) { // 计算带有下限 lower 的阶乘 n!,即 n * n-1 * n-2 ... * lower+1。
return n == lower ? 1 : n * fact(n - 1, lower);
}
英文:
Okay, I got it. What I need to do is cancel out the bigger number in the denominator. If r
is bigger than n-r
, then the formula becomes this:
n * n-1 * n-2 ... * r+1 / (n-r)!
And if n-r
is bigger than r
, the formula becomes this:
n * n-1 * n-2 ... * (n-r)+1 / r!
This makes the bigger number in the denominator smaller and n!
smaller too. Here is my code in the end:
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);
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论