为什么这样,在查找算法的时间复杂度时,对数的基数总是为2?

时间:2017-07-20 18:07:44

标签: algorithm time-complexity big-o space-complexity

考虑这段代码,

function isPrime(n):
for i from 2 to n - 1:
    if (n mod i) = 0, return false
return true

该内循环运行O(n)次并且每次执行一些计算n mod i的工作(作为非常保守的上限,这当然可以在时间O(n ^ 3)中完成)。因此,这个整体算法在时间O(n ^ 4)运行,可能更快。

我们的算法在时间O(n ^ 4)运行,但这是输入位数的函数?好吧,写出数字n需要O(log n)位。因此,如果我们让x是写出输入n所需的位数,则该算法的运行时间实际上是O(2 ^(4x)),这不是x中的多项式。

我的问题是

  

要以位为单位写入数字n,必须使用log n位(Base 10)。因此,如果我们让x为位数,则实际运行时间必须为O(10 ^(4x))。这与O(2 ^(4x))完全不同。我们怎么能承受这样的近似?

3 个答案:

答案 0 :(得分:4)

对数基数之间的转换相当于乘以某个常数。常数乘法不会影响大O复杂度类。所以对数基数对分析没有影响。

但是,你问题中的例子并不是关于对数的。这是相反的,因为它是关于指数表达式。但我并不完全理解这个例子,因为短语“它必须记录n位(基数为10)”对我来说没有意义。数字n实际上有大约log n (base 2)位,而不是基数10,正如你断言的那样。

答案 1 :(得分:2)

您的函数要么采用n的base-2表示,要么采用base-10表示,而不是两者。在第一种情况下,输入大小明确x = log_2(n),而后者则无可争议x = log_10(n)。如果您的算法花费的时间与n^4成比例(例如),那么第一台机器会O((2^x)^4 = O(2^(4x)),而后者需要O((10^x)^4) = O(10^(4x))。实际上,10^(4x)渐近地增长得比2^(4x)快得多,因为可以很容易地验证。

这通常被视为一个问题,因为假定机器模型对于给定的分析保持不变。很容易证明,改变机器模型可以改变很多关于复杂性的东西;例如,已知在单机带确定性图灵机中,检测回文在RAM机器中的线性时间和二次时间。

更重要的是给定模型中的一致性。并且,只要您保持在给定模型(机器是二进制或十进制)内,就不用担心。

"但是等等",你说,"我可以在一台机器上传入编码输入的字符串作为二进制或十进制!"这是真的。然而,在这种情况下,采用基数2表示并且需要O(n)的算法实际上比采用O(n)的十进制更快(作为输入的函数)。为什么?因为n是每种情况下输入大小的指数函数,2是小于10的基数。因此在这种情况下它确实告诉我们有用的信息(但请注意,我们在这里没有采用任何对数,刚做完指数)。

实际上,您正在将对数与指数混淆,因为两者都参与分析函数的运行时。对数的基数是可以互换的,但指数的基数不是。

答案 2 :(得分:0)

除非你使用任意大数字(因此是bignum库),否则整数适合寄存器并由CPU指令直接详细说明,这些指令需要一段时间来执行 1 ,无论&#34的数量是多少;关于"输入中的位。因此,内循环中的模运算是O(1)。

另一方面,如果n没有确实有边界,我们当然不能再说mod是O(1)。

现在,即使我们想象算法是数字位数的多项式,但你选择的基数并不重要:说mod是O(d ^ a)其中dn的小数位数(即d = log10(n));不同基数中的对数仅仅乘以乘法因子,因此我们得到log10(n)= k log2(n),因此O((log10(n))^ a)= O(k ^ a(log2(n))^ a)= O((log2(n))^ a)因为大符号并不对乘法常数感兴趣,所以你会发现它真的是一样的。

  1. 在简单的CPU上完全正确,对于每条指令,您可以准确地说出机器周期的数量;现代CPU更复杂,单个指令的成本更难以确定,但它通常不依赖于输入的确切位模式。