习题解析
虽说只有一位老哥在评论区回答了,但不管怎样,答案还是要公布的。上篇文章的代码如下,当然也可以去我的文章里面看,点这里看我的上篇文章。
int function(int n){
int sum=0;
for(int i=1;i<n+1;i++){
for(int j=n;j>i-1;j--)
for(int k=1;k<j+1;k++)
sum++;
}
return sum;
}
下面开始分析。
代码结构
这段代码结构很清晰,就是普通的嵌套循环
,这里不过是3层嵌套罢了。
代码拆解
2层循环很好算,那3层呢。用减少循环层数的思想可以降低多层循环带来的计算复杂度。从里往外拆解,先看最内层的2个循环
for(int j=n;j>i-1;j--) //1层循环
for(int k=1;k<j+1;k++) //2层循环
这里的变量涉及到了j、k、i
。先分析这两层的时间复杂度。这里很重要的一点,把i当常数看
1层循环:共执行n-(i-1)
,即n-i+1
次;j最大为n最小为i
2层循环:共执行j
次;k最小为1,最大为j;而j最大值为n,即2层循环的最大执行次数为n,随着j的递减,2层循环的执行次数不断减少
将2层循环每次的执行次数看成一个等差数列an的项,将1层循环执行次数看成这个等差数列an的项数,这样一来,两层循环的执行次数就是等差数列an的和
因为j每减1,2层循环的执行次数就减1,且j=n
时2层循环执行次数最大为n;当j=i
时,最小执行次数是i
所以等差数列通项公式如下
a
n
=
i
+
(
n
−
1
)
×
1
=
i
+
n
−
1
a_n=i+(n-1)\times1=i+n-1
an=i+(n−1)×1=i+n−1
因为1层循环执行n-i+1
次,因此等差数列共有n-i+1项
,所以等差数列前n项和为
S
n
=
(
n
−
i
+
1
)
(
i
+
n
)
2
=
n
(
n
+
1
)
2
+
i
(
1
−
i
)
2
S_n=\frac {(n-i+1)(i+n)}{2}=\frac{n(n+1)}{2} +\frac{i(1-i)}{2}
Sn=2(n−i+1)(i+n)=2n(n+1)+2i(1−i)
算到这里,因为n是问题给定的已知量,如果我们知道i是多少,那么就能求出sum++的执行次数了,所以下一步就是回到最外层的i循环
for(int i=1;i<n+1;i++)
我把整个循环稍稍修改一下
int Sn=0; //因为执行次数必为整数,因此声明为int类型
for(int i=1;i<n+1;i++){
Sn+=((n+1)n)/2 + ((1-i)*i)/2;
}
这样一来,其实就是对Sn进行求和,因此sum++的频度为:
f
r
e
q
u
e
n
c
y
=
∑
i
=
1
n
(
n
(
n
+
1
)
2
+
(
1
−
i
)
2
i
)
=
n
2
(
n
+
1
)
2
+
1
2
∑
i
=
1
n
(
i
−
i
2
)
=
n
2
(
n
+
1
)
2
+
1
2
(
n
(
n
+
1
)
2
−
1
6
n
(
n
+
1
)
(
2
n
+
1
)
)
=
n
2
+
n
3
2
+
n
(
1
+
n
)
4
(
1
−
2
n
+
1
3
)
=
2
n
3
+
3
n
2
+
n
6
\begin{aligned} frequency &= \sum_{i=1}^n (\frac{n(n+1)}{2} +\frac{(1-i)}{2}i)\\ &=\frac{n^2(n+1)}{2}+\frac{1}{2}\sum_{i=1}^n(i-i^2)\\ &=\frac{n^2(n+1)}{2}+ \frac{1}{2}(\frac {n(n+1)}{2}-\frac{1}{6}n(n+1)(2n+1))\\ &= \frac{n^2+n^3}{2}+\frac{n(1+n)}{4}(1-\frac{2n+1}{3}) \\ &= \frac{2n^3+3n^2+n}{6} \end{aligned}
frequency=i=1∑n(2n(n+1)+2(1−i)i)=2n2(n+1)+21i=1∑n(i−i2)=2n2(n+1)+21(2n(n+1)−61n(n+1)(2n+1))=2n2+n3+4n(1+n)(1−32n+1)=62n3+3n2+n
因此,答案分别为:
2
n
3
+
3
n
2
+
n
6
,
O
(
n
3
)
\frac{2n^3+3n^2+n}{6},O(n^3)
62n3+3n2+n,O(n3)
答案验证
#include<stdio.h>
int function(int n){
int sum=0;
for(int i=1;i<n+1;i++){
for(int j=n;j>i-1;j--)
for(int k=1;k<j+1;k++)
sum++;
}
printf("公式计算结果为: %d\n",(2*n*n*n+3*n*n+n)/6);
return sum;
}
int main(){
int result =function(10); //令n=10
printf("sum++执行次数为: %d",result);
}
当然你也可以试多几次,看看用公式计算所得答案和程序执行出来sum的值是否一致。
我上篇文章的地址如下:
https://blog.csdn.net/WizardrK/article/details/108538896