我正在研究算法的复杂性,我仍然无法确定某些算法的复杂性......好的,我能够找出基本的O(N)和O(N ^ 2)循环,但我在这个例程中有一些困难:
// What is time complexity of fun()?
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;
}
好的,我知道有些人可以闭着眼睛计算出来,但是我很乐意看到一个&#34;步骤&#34;通过&#34; step&#34;如果可能的话。
我解决这个问题的第一个尝试是&#34;模拟&#34;输入并将值放在某种表中,如下所示:
for n = 100
Step i
1 100
2 50
3 25
4 12
5 6
6 3
7 1
好的,此时我假设这个循环是O(logn),但不幸的是,正如我所说,没有人解决这个问题&#34; step&#34;通过&#34; step&#34;所以最后我不知道所做的一切......
在内部循环的情况下,我可以构建某种类似的表:
for n = 100
Step i j
1 100 0..99
2 50 0..49
3 25 0..24
4 12 0..11
5 6 0..5
6 3 0..2
7 1 0..0
我可以看到两个循环都在减少,我想可以根据上面的数据推导出一个公式......
有人可以澄清这个问题吗? (答案是O(n))
答案 0 :(得分:1)
让我们将这个分析分解为几个步骤。
首先,以内部for循环开始。可以直接看到这需要i
个步骤。
接下来,考虑在算法过程中会假设哪些不同的值i
。首先,考虑n
是2的幂的情况。在这种情况下,i
从n
开始,然后是n/2
,然后是n/4
,等等直到它达到1
,最后到达0
并终止。因为内部循环每次都需要i
个步骤,所以在这种情况下fun(n)
的步骤总数正好是n + n/2 + n/4 + ... + 1 = 2n - 1
。
最后,说服自己这可以概括为2 的非权力。给定输入n
,找到大于n
的2的最小幂并将其称为m
。显然,n < m < 2n
,fun(n)
所需的2m - 1
步数少于4n - 1
。因此fun(n)
是O(n)
。
答案 1 :(得分:1)
另一种可能看待它的简单方法是:
你的外部循环在n处初始化i(可以被认为是步/迭代器)并且在每次迭代之后将i除以2。因此,它执行i / 2语句log2(n)次。所以,考虑它的方法是,你的外循环运行log2(n)次。无论何时将数字连续除以基数直到达到0,您都可以有效地执行此除法日志次数。因此,外环是O(log-base-2 n)
你的内循环迭代j(现在是迭代器或步骤)从0到i 外循环的每次迭代。我取n的最大值,因此你的内循环将具有的最长运行时间为0到n。因此,它是O(n)。
现在,您的程序运行如下:
Run 1: i = n, j = 0->n
Run 2: i = n/2, j = 0->n/2
Run 3: i = n/4, j = 0->n/4
.
.
.
Run x: i = n/(2^(x-1)), j = 0->[n/(2^(x-1))]
现在,运行时间总是&#34;倍增&#34;对于嵌套循环,所以 O(log-base-2 n)* O(n)给出整个代码的O(n)