A)
sum = 0;
for(i=1;i<2*n;i++)
for(j=1;j<i*i;j++)
for(k=1;k<j;k++)
if (j % i == 1)
sum++;
b)中
sum = 0;
for(i=1;i<2*n;i++)
for(j=1;j<i*i;j++)
for(k=1;k<j;k++)
if (j % i)
sum++;
我在寻找算法分析问题时偶然发现了上面的两个伪代码。上述两个片段的答案分别为O(n 4 )和O(n 5 )。
请注意,此处的运行时间对应于操作的次数 sum ++被执行。
当唯一的区别是n
循环测试等于if
时,上述两种算法的时间复杂度如何相差1
?我如何计算这样一个问题的O(n)复杂度?
答案 0 :(得分:1)
算法A
让我们调用f(n)
在外循环级别聚合的操作数,g(n)
为第一个内循环,h(n)
为最内循环。
我们可以看到
f(n) = sum(i=1; i < 2n; g(i))
g(i) = sum(j=1, j < i*i; h(j))
h(j) = sum(k=1; k < j; 1 if j%i = 1, else 0)
j%i = 1
j
从1到i*i
的变化次数是多少? i
的以下值恰好j
次:
j = 0.i + 1
j = 1.i + 1
j = 2.i + 1
...
j = (i-1)*i + 1
所以:
h(j) = sum(k=1; k < j; 1 if `j%i = 1`, else 0)
= i
=> g(i) = sum(j=1, j < i*i; h(j))
= sum(j=1, j < i*i; i)
= i*i * i = i^3
=> f(n) = sum(i=1; i < 2n; g(i))
= sum(i=1; i < 2n; i^3)
<= sum(i=1; i < 2n; 16.n^3) // Here just cap every i^3 with (2n)^3
<= 32.n^4
=> f(n) = O(n^4)
算法B
(使用与算法A相同的命名约定)
我们将j%i
投射到true
的次数是多少?每次j%i
与0不同。这次发生了多少次?我们需要删除j
为i
的倍数的事件,i
,2.i
,... (i-1).i
。整数1到i*i
,其中包含i*i
个数字。此数量为i*i - (i-1) = i^2 - i + 1
。
结果,
h(j) = sum(k=1; k < j; 1 if j%i = 1, else 0)
= i^2 - i + 1
= i^2 // dropping the terms i and 1 which are dominated by i^2 as i -> +Inf.
=> g(i) = sum(j=1, j < i*i; h(j))
= sum(j=1, j < i*i; i^2)
= i*i * i^2
= i^4
=> f(n) = sum(i=1; i < 2n; g(i))
= sum(i=1; i < 2n; i^4)
<= sum(i=1; i < 2n; 32.n^4) // Here just cap every i^4 with (2n)^4
<= 64.n^5
=> f(n) = O(n^5)
底线
算法A和B之间复杂性的差异来自以下事实:
i
j
值为i%j = 1
i^2 - i + 1
j
值为i%j <> 0