答案解析——接上篇文章(程序员过不去的一道坎--时间复杂度)

习题解析

虽说只有一位老哥在评论区回答了,但不管怎样,答案还是要公布的。上篇文章的代码如下,当然也可以去我的文章里面看,点这里看我的上篇文章

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+(n1)×1=i+n1
因为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(ni+1)(i+n)=2n(n+1)+2i(1i)
算到这里,因为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=1n(2n(n+1)+2(1i)i)=2n2(n+1)+21i=1n(ii2)=2n2(n+1)+21(2n(n+1)61n(n+1)(2n+1))=2n2+n3+4n(1+n)(132n+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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值