foo(int n)
{
int s=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=i*i;j++)
if(j%i==0)
for(k=1;k<=j;k++)
s++;
}
上述代码的时间复杂度是多少?
我把它作为O(n ^ 5),但它不正确。
答案 0 :(得分:2)
复杂性为O(n^4)
。
对于每个i
,最内层循环将执行i
次。 (i
内i
的倍数0..i*i
它将像内循环一样运行
j = 0 1 2...i i+1 ...2*i ....3*i .... 4*i .... 5*i... i*i
x x x x x x
\------/\--------/\-------/ \------/
这些x
表示执行具有复杂性j
的最内层for循环。其余的时间没有触及,只是测试完成而且失败了。
现在检查一下,这些\-----/
有i*j
(j = 1,2,3...i)
循环和i
检查。
现在我们准确地i
次。
So total work = i*(1+1+1+...1) + i*(1+2+3+..i)
= i*i+ i*i*(i+1)/2 ~ i^3
使用外部循环,它将是n^4
。
现在它是什么意思。整个工作可以像这样划分
O(i*j+i)
^^^ ^
| The other cases when it simply skips
The innermost loop executed
现在,如果我们迭代j
,那么它将具有复杂性O(n^3)
。
添加外部循环后,它将为O(n^4)
。
答案 1 :(得分:1)
您的函数计算四维金字塔数(A001296)。可以使用以下公式计算s
的增量数:
a(n) = n*(1+n)*(2+n)*(1+3*n)/24
因此,函数的复杂性为O(n 4 )。
它不是O(n 5 )的原因是if (j%i == 0)
只对i
的倍数进行“有效载荷”循环,其中我们有i
{在j
到i 2 范围内的所有1
中{1}}。
因此,我们为最外层循环添加一个,为中间循环添加一个,为最内层循环添加两个,因为它迭代到i 2 ,总共4个。 / p>
为什么只有一个中间(j)?它运行到i 2 对吗?
也许更容易看出我们是否重写代码以排除条件:
int s=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=i;j++)
for(int k=1;k<=i*j;k++)
s++;
return s;
此代码生成相同数量的“有效负载循环”迭代,但不是“过滤掉”跳过内部循环的迭代,而是通过计算最内层循环中k
的终值来将它们从考虑中删除为i*j
。