时间复杂度和整数输入

时间:2018-01-03 11:10:00

标签: time-complexity big-o

我遇到了一个问题,要求在下面的代码中描述Big O中的计算复杂性:

i = 1;
while(i < N) {
    i = i * 2;
}

我发现this Stack Overflow问题要求答案,最多的答案说它是Log2(N)。

首先想到答案看起来是正确的,但我记得学习了伪多项式运算时,以及计算复杂度如何衡量输入长度的难度,而不是值。

因此,对于整数输入,复杂性应该是输入中的位数。

因此,这个函数不应该是O(N)吗?因为循环的每次迭代都会将i中的位数增加1,直到它达到与N相同的位。

3 个答案:

答案 0 :(得分:0)

这取决于重要的问题:&#34;乘法常数运算&#34;?

在现实世界中,它通常被认为是常量,因为你有固定的32位或64位数,并且它们相乘总是相同(=恒定)的时间。 另一方面 - 你有限制N&lt; 32/64位(或任何其他如果使用它)。

理论上你不考虑乘法作为常数运算,或者对于一些特殊的算法,其中N可以增长太多而无法忽略乘法复杂性,你是对的,你必须开始考虑乘法的复杂性。

乘以常数(在这种情况下为2)的复杂性 - 每次都必须经过每一位,并且你有log_2(N)位。

在到达log_2(N)

之前,您必须点击N

log_2(N) * log_2(N) = O(log_2^2(N))

的复杂性结束

PS:Akash有一个好处,即乘以2可以写为常量运算,因为二进制中唯一需要的是&#34;加零&#34; (类似于在&#34中乘以10;人类可读&#34;格式,你只需加零4333 * 10 = 43330)

然而,如果乘法不那么简单(你必须经历所有位),那么前面的答案是正确的

答案 1 :(得分:0)

此代码可能在以下功能中找到:

function FindNextPowerOfTwo(N) {
    i = 1;
    while(i < N) {
        i = i * 2;
    }
    return i;
}

这里,输入可以被认为是k位无符号整数,我们可以将其想象为具有k位的字符串。因此输入大小为k = floor(log(N)) + 1位输入。

赋值i = 1应解释为创建一个新的位串并为其分配长度为一位的字符串1。这是一个恒定的时间操作。

循环条件i < N比较两个位串以查看哪个代表较大的数字。如果智能地实现,这将花费时间与两个位串中较短的长度成比例,其总是i。正如我们将看到的,i位串的长度从1开始并增加1,直到它大于或等于N位串的长度,k。当N不是2的幂时,i位字符串的长度将达到k + 1。因此,在最坏的情况下,评估条件所花费的时间与1 + 2 + ... + (k + 1) = (k + 1)(k + 2)/2 = O(k^2)成正比。

在循环中,我们将i一遍又一遍地乘以2。此操作的复杂性取决于如何解释乘法。当然,有可能以这样一种方式表示我们的位串,即我们可以通过执行位移并在末尾插入零来智能地乘以2。这可以做成恒定时间操作。如果我们没有注意到此优化并执行标准长乘法,我们会扫描i的位字符串一次以写出一行0并再次写出i使用额外的0,然后我们通过扫描这两个字符串来执行常规添加。这里每个步骤所花费的时间与i位串的长度(实际上,加上一个)成比例,因此整个事件与i的比例成正比。位串长度。由于i的位串长度为1, 2, ..., (k + 1),因此总时间为2 + 3 + ... + (k + 2) = (k + 2)(k + 3)/2 = O(k^2)

返回i是一个恒定时间操作。

将所有内容放在一起,运行时间由c * k ^ 2形式的函数从上方和下方限定,因此最坏情况复杂性的约束为Theta(k^2) = Theta(log(n)^2)

答案 2 :(得分:-1)

在给定的示例中,您没有将i的值增加1,而是每次都将它增加一倍,因此它朝N移动速度快2倍。通过将它乘以2可以减小搜索空间的大小(我到N之间的一半;即,将输入空间减少2倍。因此,程序的复杂性为 - log_2(N)。

如果你偶然发生了 -

i = i * 3;

程序的复杂程度为log_3(N)。