Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/352.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.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
计算阶乘n的时间复杂度是多少!使用Java';s大整数_Java_Algorithm_Time Complexity_Biginteger_Factorial - Fatal编程技术网

计算阶乘n的时间复杂度是多少!使用Java';s大整数

计算阶乘n的时间复杂度是多少!使用Java';s大整数,java,algorithm,time-complexity,biginteger,factorial,Java,Algorithm,Time Complexity,Biginteger,Factorial,假设算法如下所示: public static BigInteger getFactorial(int num) { BigInteger fact = BigInteger.valueOf(1); for (int i = 1; i <= num; i++) fact = fact.multiply(BigInteger.valueOf(i)); // ? time complexity return fact; } public静态biging

假设算法如下所示:

public static BigInteger getFactorial(int num) {
    BigInteger fact = BigInteger.valueOf(1);
    for (int i = 1; i <= num; i++)
        fact = fact.multiply(BigInteger.valueOf(i)); // ? time complexity
    return fact;
}
public静态biginger getFactorial(int num){
BigInteger事实=BigInteger.valueOf(1);

对于(int i=1;i而言,
fact
中包含的位数是
log(fact)
O(log(n!))==O(nlogn)
,因此
n!
中的位数与
nlogn
成比例增长。因为您的算法将值堆积到部分积上,而不会将它们拆分为较小的中间值(分治方式),我们可以断言,在计算
n!
时,其中一个被乘的数字将小于
n
。使用小学乘法,我们有
O(logn*nlogn)
时间将这些数字相乘,我们有
n-1
倍数,所以这是
O(n*logn*nlogn)==O((nlogn)^2
。我确实认为这是小学乘法的一个严格上限,因为尽管开始乘法要小得多,后一半都大于
O((n/2)log^2(n/2))
,其中有
(n/2)
,所以
O((n/2)^2*log^2(n/2))==O((nlogn)^2)


然而,
biginger
完全有可能使用Karatsuba乘法、Toom Cook乘法,甚至可能是Schönhage–Strassen算法。我不知道这些算法如何处理大小变化如此大的整数(
logn
vs
nlogn
),所以我不能给出一个严格的上界。我所能做的就是推测它将小于
O(n*F(nlogn))
,其中
F(x)
是使用特定算法乘以两个长度数
x

事实中的位数是
log(fact)
,而
O(log(n!))==O(nlogn)
如前所述。因此,只需应用
biginger
使用的任何乘法算法即可。您好@DillonDavis,谢谢,如果biginger使用Karatsuba乘法,加上O(x**1.585),总复杂度是否为O((nlogn)^1.585)?老实说,我不是100%确定。两个相乘的值甚至不接近相同的大小,因此时间可能小于
O(x**1.585)
,另一方面,我们进行
num
相乘,因此其中可能有另一个因子
n
。它肯定是
O((n^2logn)^1.585)
,但很可能有一个更严格的上限。事实上,使用小学乘法,我们已经有了
O(logn*(nlogn))
,因为其中一个被乘法的数字最多是
num
n
),所以这本身就给出了
O((nlogn)^2)
,这比我给你的另一个估计要好。好吧,Java的BigInteger乘法使用Karatsuba、Toom Cook 3路,但还没有Schönhage Strassen。当然还有小值的教科书。如果算法不是“除法和征服法”,那么你会不断地用一个“小”乘以一个快速增长的大数一个是SSSLLLOOWWW。@RudyVelthuis我同意你的最后一点,但是OP问的是factorial.correct的具体实现的时间复杂度。我只是想指出这种天真方法的缺陷。我想告诉你在Java.FWIW中使用哪些算法来乘以大整数。我刚刚意识到t如果其中一个数字低于阈值(并且上面的循环索引远低于阈值),将使用教科书,所以这里根本不使用Karatsuba等。只有教科书,除非你使用分治算法。@RudyVelthuis:我尝试了几种不同的方法来计算阶乘作为答案。安排事情有目的地利用更复杂的算法明显更快。@JamesKPolk关于我们能以多快的速度将素数筛选到
n
,使用平方运算(在
BigInteger
中的引擎盖下)进行求幂以更快地获得结果可能会更快。
    public BigInteger getFactorial2(long n) {
        return subFactorial(1, n);
    }
    private BigInteger subFactorial(long a, long b) {
        if ((b - a) < 10) {
            BigInteger res = BigInteger.ONE;
            for (long i = a; i <= b; i++) {
                res = res.multiply(BigInteger.valueOf(i));
            }
            return res;
        } else {
            long mid = a + (b - a) / 2;
            return subFactorial(a, mid).multiply(subFactorial(mid + 1, b));
        }
    }