1 i ← 1
2 while i < n/4
3 do
4 j ← 2i
5 while j < n
6 do
7 j ← j + 1
8 i ← i + 1
b) 1 i ← n
2 while i > 1
3 do
4 j ← i
5 while j < n
6 do
7 j ← 2j
8 i ← i − 1
c) 1 i ← 1
2 while i < n
3 do
4 j ← 0
5 while j ≤ i
6 do
7 j ← j + 1
8 i ← 2i
鉴于这三个程序,找到每个程序的时间复杂度最简单的方法是什么?我可以说第一个可能是O(n ^ 2)。但是,有一种简单的方法来解决这个问题吗?我明天有考试。
答案 0 :(得分:3)
(我会在总和限制中忽略1,舍入等)
A)
在内循环中,您执行n - 2i - 1
次操作。在外循环中,您执行n/4 - 1
。所以复杂性是:
所以你对第一个的回答是正确的。
B)
在内部循环中,j
每次都会加倍,因此会呈指数增长;因此内循环采用对数时间 - log (n / i)
。 (基数2但忽略WLOG)。内部i
的划分是因为j
从i
开始,因此相当于从1开始并逐渐增长到n / i
。在外部循环中,您执行n - 1
操作。
(最后一步来自 Stirling的近似值)
C)
在内循环中,您执行i + 1
操作。在外圈i
从1增加到n
,所以log n
。
N.B。我注意到TypeKazt的答案存在显着差异;这说明你不能简单地将内循环的复杂性与外循环的“复杂性”相乘,并且内循环的边界条件在确定上是重要的。
编辑:作为我对TypeKazt(hehe sorry buddy)的大胆指责的补充证明,这是我从C#实现获得的一些测试数据:如您所见,A(线性标度)的复杂度为O(n^2)
,而B和C(对数标度)的复杂度为线性。
代码:
static int A(int n)
{
int c = 0;
for (int i = 0; i < n / 4; i++)
for (int j = 2 * i; j < n; j++)
c++;
return c;
}
static int B(int n)
{
int c = 0;
for (int i = n; i > 1; i--)
for (int j = i; j < n; j *= 2)
c++;
return c;
}
static int C(int n)
{
int c = 0;
for (int i = 1; i < n; i *= 2)
for (int j = 0; j <= i; j++)
c++;
return c;
}
P.S。我知道SO的政策不是为了照顾别人,而是为了一个人通过实例学习,所以我希望这能帮助你理解复杂性分析的简单分析方法。