如何降低程序的时间复杂度,以便在python中找到阶乘的长度?

时间:2015-03-01 15:02:52

标签: python python-2.7

我遇到了一个问题,我首先找到一个数字的阶乘,然后返回在阶乘中获得的数字位数。 我写了这个程序,它工作得很好。但时间是5.0015秒,我必须在1秒内完成。如何减少这个?

以下是我的计划:

def factorial(n):
    fact = 1
    for y in xrange(1,n+1):
        fact = fact * y
    return fact

t = int(raw_input())
raw_input()
for x in xrange(t):
    n = int(raw_input())
    print len(str(factorial(n)))

3 个答案:

答案 0 :(得分:3)

使用数学的力量,避免完全计算阶乘。

数字的基数10对数是10需要被提升到等于该数字的幂。例如,math.log10(10) == 1math.log10(11) == 1.0413926851582251math.log10(100) == 2

这意味着最小整数比数字的log10大得多(即ceil(log10(n)) + (1 if log10(n).is_integer() else 0))是该数字中的位数。

此外,log10(a * b) = log10(a) + log10(b)

这意味着log10(factorial(n)) == sum(log10(a) for a in range(1, n+1))

最后,该阶乘的长度为:

math.ceil(sum(math.log10(a) for a in xrange(1, n+1)))

(更多信息:http://en.wikipedia.org/wiki/Logarithm

答案 1 :(得分:1)

我建议使用Stirling's approximation for log(n!)

from math import ceil, log, pi

def log_fact(n):
    # using Stirling's approximation to calculate log10(n!)
    n = float(n)
    return (
        n * log(n)
        - n
        + log(2 * pi * n) / 2.
        + 1/(  12 * n   )
        - 1/( 360 * n**3)
        + 1/(1260 * n**5)
    ) / log(10)

猜测n的值大约为60000;测试我得到了

import math
n = 60000

%%timeit
# @SheeshMosin
len(str(factorial(n)))                                 # 3.93 s

%%timeit
# @MaxNoel
math.ceil(sum(math.log10(a) for a in range(1, n+1)))   # 16.1 ms
                                                       # (250 times faster)

%%timeit
# @HughBothwell
math.ceil(log_fact(n))                                 # 3.62 µs
                                                       # (1.08 million times faster)

答案 2 :(得分:-4)

您可以尝试递归函数。