Algorithm 不一致性的时间复杂度分析
我有以下代码:Algorithm 不一致性的时间复杂度分析,algorithm,time-complexity,Algorithm,Time Complexity,我有以下代码: int fun(int n) { int count = 0; for (int i = n; i > 0; i /= 2) for (int j = 0; j < i; j++) count += 1; return count; } 因为O(1+2+4+..+n/4+n/2)=O(n)。但是由于循环运行了log(n)次,因此它也可以是log(n) 为什么前者不是:log(n)乘以外循环*log(n)乘以内循环,所以,log(
int fun(int n)
{
int count = 0;
for (int i = n; i > 0; i /= 2)
for (int j = 0; j < i; j++)
count += 1;
return count;
}
因为O(1+2+4+..+n/4+n/2)=O(n)
。但是由于循环运行了log(n)
次,因此它也可以是log(n)
为什么前者不是:log(n)
乘以外循环*log(n)
乘以内循环,所以,log(n)log(n)
我做错了什么?第一个代码段的外循环执行
O(logn)
次,每次迭代,内循环执行O(I)
次。如果您将任意数量的项求和为n/2^k
,您将得到O(n)
第二段代码有
O(logn)
次O(1)
运算的迭代,并且常数的对数量之和仍然是对数的。第二段代码的时间复杂度不应计算为一系列O(1+2+4+…+n/4+n/2)=O(n)
,因为它不是那个系列
注意第一个。它被计算为一个系列,因为计算内部
for
循环执行的次数,然后将所有循环(系列)相加,以获得最终的时间复杂度
当i=n
内部for
循环执行n
次当
i=(n/2)
internalfor
循环执行n/2
次当
i=(n/4)
internalfor
循环执行n/4
次等等
但在第二个例子中,没有要添加的系列。它只是得到一个公式
(2^x)=n
,其计算结果为x=logn
(2^x)=n
通过注意i
以1
开始,当它变为2
时,乘以2
,直到它达到n
因此,我们需要找出
2
需要乘以2
多少次才能达到n
因此,公式
(2^x)=n
,然后求解x
在第一个示例中,循环中没有O(1)语句,就像(int j=0;j中的一样。如果在第二个示例中使用第一个示例的相同内部循环,则返回到相同的复杂性。第一个循环不是O(n*log(n))
;这很容易证明,因为你可以在O(2n)
中找到一个上界,它相当于O(n)
第二个上界实际上可以看作是一个系列,i=1;O(1),i=2;O(1).
O(log(n)*1)=O(log(n))
。谢谢@DarshanChaudhary,也是这样,但我发现我解释的方法更简单,更容易掌握。@DarshanChaudhary,不管怎样,知道所有解决问题的方法总是好的,这很有趣。:)你能详细解释一下“如果你把n/2^k形式的对数n项求和,你会得到O(n)”这句话吗?我知道外循环会运行log(n)
,内循环每次运行都会运行O(I)
。@DarshanChaudhary,第一个项已经是O(n)
,所以总和不小。另一方面,很容易看出,n/2+n/4+n/8+…
小于或等于n
:事实上,当k=1时,和x
的值为n/2,正好是0和n之间的中间点。每次在总和中添加下一项时,都会将x
移动到当前x
和n
之间的中间点。显然,它不能超过n
。是的,在编辑之后,它是非常有意义的。谢谢我不明白为什么第一个不是O(nlog(n))
。外部循环运行,log(n)
次,每次,内部循环都有O(n)、O(n/2)、O(n/4)…
。因此,内部循环有O(n)
,外部循环有O(log(n))
。因此,O(nlog(n))
。为什么不呢?@DarshanChaudhary内部循环仅第一次运行n次。运行内部循环log(n)
次,但每次内部循环的循环数下降时。要获得n*log(n)
的复杂度,您需要运行所有内部循环,使其由n
个循环组成,但实际情况并非如此。如果您对其中一个循环感到满意,则应注意。
for(i = 1; i < n; i *= 2)
//O(1) statements