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)
internal
for
循环执行
n/2

i=(n/4)
internal
for
循环执行
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