java - 使用内存计算二项式 choose(n,r) = n!/(r!(n-r)!)

标签 java algorithm

二项式函数 choose(n,r) = n!/(r!(n-r)!) 如何编写一个程序来计算 10^8 = 1 亿个随机二项式,其中 N 从 1 到 52 随机选择,R 随机选择 0 到 n。

需要使用记忆化或类似方法在 O(1) 时间内计算二项式。

我的代码就是这样。我知道在每次递归中,一个元素可能会计算两次,我不知道如何通过使用内存来提高效率。

public static int choose(int n, int k){
    if(k == 0) return 1;

    return (n * choose(n - 1, k - 1)) / k;
}

最佳答案

首先,对于整数数据类型,您可能会得到太大的数字... Proof .

这个想法是你一步一步来......乘以被除数的后续数字并除以除数的后续数字。

public class Binom {

    private long[][] mapped;

    public Binom(){
        mapped = new long[52][52];
    }

    public long binom(int n, int r) {
        if (r == 0)
            return 1;
        if (r == 1)
            return n;

        if(r > n-r)
            r = n-r;
        long toReturn = 1;
        for (int i = 1, m = n; i <= r; i++, m--){
            toReturn = toReturn*m/i;
        }
        return toReturn;
    }

    public long[][] getMapped() {
        return mapped;
    }
}

我的基准:

public class Benchmark {

    public static void main(String[] args) {
        long start = System.nanoTime();
        Random random = new Random();
        int count = 1;
        Binom binom = new Binom();
        long[][] mapped = binom.getMapped();
        for (int i = 1; i <= 100_000_000; i++) {
            int n = 1 + random.nextInt(52);
            int r = 1 + random.nextInt(n);
            long result = mapped[n-1][r-1];
            if (result != 0) {
                System.out.println(count++ + ". Binomial for n: " + n + " and r: " + r + " equals " + result + ".");
            } else {
                result = binom.binom(n, r);
                mapped[n-1][r-1] = result;
                System.out.println(count++ + ". Binomial for n: " + n + " and r: " + r + " equals " + result + ".");
            }
        }
        System.out.println("The whole lasted " + ((System.nanoTime() - start)/1_000_000_000) + " seconds.");
    }
}

输出结束:

99999995. Binomial for n: 3 and r: 3 equals 1.
99999996. Binomial for n: 19 and r: 17 equals 171.
99999997. Binomial for n: 26 and r: 20 equals 230230.
99999998. Binomial for n: 32 and r: 13 equals 347373600.
99999999. Binomial for n: 20 and r: 14 equals 38760.
100000000. Binomial for n: 3 and r: 3 equals 1.
The whole lasted 342 seconds.

如果不打印它会更快...您只需要计算那些 1378=(52*52/2) 对的二项式系数。

关于java - 使用内存计算二项式 choose(n,r) = n!/(r!(n-r)!),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41991789/

相关文章:

java - Android Jsonarray无法转换为json对象

java - 使用错误类型的数据创建的强类型列表

algorithm - 算法设计问题矩形覆盖不同的小矩形或正方形

c++ - 具有特定最小距离的特定正方形(而非单位正方形)中的二维泊松盘采样

algorithm - NP问题,需要一些细节?

java - 如何将 BlockHound 添​​加到 Spring Boot 应用程序以检测阻塞调用?

java - inflater.inflate(R.layout.) 找不到 Fragment.xml

java - 将相同的位序列解释为不同的数据类型

algorithm - 进行递归二分查找

python - 如何从 python 中的排名组中随机选择数字,以创建特定长度的列表