算法分析之【时间复杂度】

时间复杂度


当电脑运行下面这段代码的时候,执行任何一条语句都需要花费时间(为了方便讨论,这里我们把每一条语句的执行时间都看做是一样的,记为一个时间单元
在这里插入图片描述
这个程序有这么几个地方消耗了时间


蓝色框的两条语句,花费2个时间单元

② 黑色框的一条语句,花费n+1个时间单元

红色框的两条语句,花费2*n个时间单元


那么一共花费了3n+3个时间单元,可以看出,程序消耗的时间和n成线性关系

  • 用T(n)表示这个程序运行了多长时间,那么这个程序运行的时间就可以写成T(n)=3n+3。其中的n被我们称为问题的规模,其实就是处理的问题的大小

在这里插入图片描述
我们常常会对这个函数进行简化,使得它既简单又不失函数的主要特性
所以一般只关心随着问题规模n趋于无穷时函数中对函数结果影响最大的项,也就是最高次项

举个栗子:

  • T(n)=n+1 忽略常数项 :T(n)~n
  • T(n)=n+n2 忽略低阶项: T(n)~n2
  • T(n)=3n 忽略最高阶的系数: T(n)~n

至于判断哪个是高阶项,哪个是低阶项,只需记住下面的大小关系就行了,到时按照这个进行忽略(忽略相对较小的)

在这里插入图片描述
简化后的式子被称为这个程序算法的时间复杂度,记做O(f(n)),f(n)就是简化后的式子,比如说刚开始讨论的T(n)=3n+3,简化后T(n)~f(n)=n,那我们记为O(n)

时间复杂度可以表示某个算法的运行时间的趋势,大致地度量算法效率的好坏


时间复杂度的计算

计算时间复杂度大O的方法

一、得出运行时间的函数
二、对函数进行简化

  1. 常数1取代运行时间中所有加法常数
  2. 修改后的函数中,只保留最高阶项
  3. 如果最高阶项存在 且系数不为1,则忽略这个项的系数(即令其系数为1

举个栗子:

int n = 0;
n = n + 6;
printf(n);

T(n)=3(三条语句1+1+1),对这个函数进行简化,用常数1取代常数3,然后取代后的函数没有最高阶项,那么这个算法的时间复杂度就是O(1).
O(1)也被称为常数阶
如果每次都要把时间函数算出来,挺麻烦的,可以耍耍小聪明,一般来说,最内层执行次数最多的语句就决定了整个算法的趋势

for(int i = 0; i < n; i++)
	printf("哈");

这个内层打印语句需要循环n次,随着问题规模n的增加会呈线性增加,可以判定其时间复杂度为O(n)

按照这个方法就很容易得出下面这个嵌套的两层for循环的时间复杂度为O(n2)

for(int i = 0; i < n; i++) {
	for(int j = 0; j < n; j++) {
		cout << "平方阶" << endl;
	}
}

有一个很神奇的函数——对数函数,它随着自变量的增大,因变量增长的很慢
在这里插入图片描述
下面这段代码的复杂度就为对数级别O(logn)

int sum = 1;
while(sum < n) {
	sum = sum * 2;
}

和之前的分析方法一样,我们着重看执行次数最多的内层代码语句

sum = sum * 2;

每循环一次,sum就给自身乘以2,乘了多少次就跳出循环了呢(大于等于n)?不知道,就设为x吧,那么 2x=n,解出 x=log2n,这说明随着n的增大,最消耗时间的内层语句是呈对数变化的。

感谢阅读~


发布了12 篇原创文章 · 获赞 24 · 访问量 2606

猜你喜欢

转载自blog.csdn.net/qq_43974000/article/details/104131438