【问题标题】:How to reduce time complexity of a program for finding length of a factorial in python?如何降低在python中查找阶乘长度的程序的时间复杂度?
【发布时间】:2015-03-01 15:02:51
【问题描述】:

我遇到了一个问题,我必须首先找到一个数字的阶乘,然后返回在阶乘中获得的位数。 我编写了程序,它运行良好。但时间是 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)))

【问题讨论】:

  • 它不会改变时间复杂度,但使用内置函数会更简单,可能更快:len(str(math.factorial(n)))
  • 我已经试过了。但我必须降低时间复杂度
  • 首先你的代码不是很清楚。如果您不使用它,为什么要定义length?你为什么要循环而不是只做print len(str(factorial(n)))
  • @HerrActress,这很可能是一个在线代码问题,您必须使用 raw_input 来接收参数
  • 即使是 memozation 也不会让您获得更好的复杂性(但它可以提高速度)。对于这个问题有一个有趣的看法,你可以查看这个问题:stackoverflow.com/questions/9815252/…

标签: python python-2.7


【解决方案1】:

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

以 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!的长度失败?
【解决方案2】:

我建议使用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)

【讨论】:

    【解决方案3】:

    您可以尝试使函数递归。

    【讨论】:

    • 那将如何降低时间复杂度?
    • 递归不会降低复杂性,并且会在大数字时开始失败,因为它会达到最大递归深度
    猜你喜欢
    • 2016-01-08
    • 2020-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-01
    • 2012-07-28
    相关资源
    最近更新 更多