2010-02-24 63 views
18

什么是一个递归程序,找了一些n的阶乘的复杂性?我的直觉是它可能是O(n)复杂递归阶乘程序的

+8

我不知道,男人。我可以编写一个非常糟糕的递归阶乘程序,至少需要O(n!)个时间才能完成。如果你想分析算法,你需要实际的算法。 – Welbog 2010-02-24 15:44:00

回答

29

如果你把乘法为O(1),那么,O(N)是正确的。但是请注意,乘以任意长度x的两个数字是O(1)有限硬件 - 如x趋于无穷大,需要乘的时间长(例如,如果你使用Karatsuba multiplication,这是O(x ** 1.585))。

理论上可以做足够庞大的数字与Schönhage-Strassen更好,但我承认我有一个没有任何现实世界的经验。 x,“长度”或“数字位数”(无论在什么基础上,对于N的大O无关紧要,当然会随着O(log N)的增长而增长)

如果您的意思是将您的问题限制为足够短号码在O(1)相乘,那么就没有办法N能“趋于无穷大”,因此大O记法是不适当的

+0

你只能乘以适合你的记忆的数字。所以我不明白乘法是如何克服O(1)的。你能给我一个详细的解释吗? – tur1ng 2010-02-24 16:02:22

+0

@ tur1ng,对于时间*和*额外空间[[输入和输出所需的显而易见的空间,这将是荒谬的计数]],你有大O行为(尽管除非明确提及空间,否则通常意味着时间)。乘以O(1)的额外空间和'O((log N)** 1.585)'及时(与Karatsuba)。 “物理可访问的宇宙”(因此任何实际上可以想象的机器)都是有限的这一事实与CS无关:通常分析(隐含地)假设一个“图灵机”,其定义为具有无限长的“磁带”(无限存储)。 – 2010-02-24 16:08:37

+0

BTW @ tur1ng,你应该更熟悉图灵机和它们无限长的磁带(“适合你的记忆” - pah! - ) - 从http://en.wikipedia.org/wiki开始/ Turing_machine。 – 2010-02-24 16:09:56

11

假设你正在谈论的最幼稚的阶乘算法直到永远。

factorial (n): 
    if (n = 0) then return 1 
    otherwise return n * factorial(n-1) 

是的,算法是线性的,为O运行(n)的时间:T他是这样的,因为它每次递减值n时间执行一次,并递减值n直到它到达0,这意味着该功能被称为递归n倍。当然,这是假定减量和乘法都是不变的操作。

当然,如果您实现阶乘一些其他的方式(例如,使用递归除了代替乘法),您可以用更多的时间,复杂的算法结束。虽然我不会建议使用这种算法。

19

当您表达算法的复杂性时,它总是作为输入大小的函数。只有在您乘法的数字具有固定大小时,才会假设乘法运算为O(1)。例如,如果您想确定计算矩阵乘积的算法的复杂度,则可以假定矩阵的各个分量具有固定大小。那么假设两个单独矩阵组件的乘法是O(1)是有效的,并且您将根据每个矩阵中的条目数来计算复杂度。

但是,如果你想找出一种算法的复杂度来计算N!你必须假设N可以任意大,所以它是无效的假定乘法是O(1)操作。

如果要将n位数与m位数相乘,那么天真算法(您手动完成的操作)需要时间O(mn),但算法更快。

如果你要分析的简单算法的复杂计算N!

factorial(N) 
     f=1 
     for i = 2 to N 
      f=f*i 

     return f 

然后在for循环的第k个步骤中,您通过k乘以(k-1)!。用于表示(k-1)!的位数是O(k log k),用于表示k的位数是O(log k)。因此,将(k-1)!k相乘所需的时间为O(k (log k)^2)(假设您使用天真乘法算法)。随后的时间由算法所花费的总金额时每一步所采取的总和:

sum k = 1 to N [k (log k)^2] <= (log N)^2 * (sum k = 1 to N [k]) =
O(N^2 (log N)^2)

您可以通过使用更快的乘算法,像Schönhage-改善这一性能Strassen对于2位n位数需要时间O(n*log(n)*log(log(n)))

提高性能的另一种方法是使用更好的算法来计算N!。我知道的最快的计算首先计算N!的素数因子分解,然后乘以所有素数因子。

+0

+1用于解释乘法的时间分析 – Moshe 2012-11-16 03:15:04