数字太大,尝试解决LeetCode独特路径问题。

huangapple go评论87阅读模式
英文:

Numbers Too Big While Trying To Solve Leetcode Unique Paths Problem

问题

我正在尝试解决LeetCode上的Unique Paths问题。基本上,问题是给你一个mn的网格,你需要计算从左上角到右下角的路径数量,只能向下或向右移动。

我正在使用数学方法,这个方法相当复杂,但基本公式如下:

(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);
}

huangapple
  • 本文由 发表于 2020年3月16日 13:05:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/60700581.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定