时间复杂度的定义:在计算机科学中,算法的时间复杂度是一个函数,它定量描述了该算法的运行时间。一个算法执行所耗费的时间,从理论上说,是不能算出来的,只有你把你的程序放在机器上跑起来,才能知道。但是我们需要每个算法都上机测试吗?是可以都上机测试,但是这很麻烦,所以才有了时间复杂度这个分析方式。一个算法所花费的时间与其中语句的执行次数成正比例,算法中的基本操作的执行次数,为算法的时间复杂度。
总结:求算法的时间复杂度,就是求它的基本操作执行次数
实际中我们计算时间复杂度时,我们其实并不一定要计算精确的执行次数,而只需要大概执行次数,那么这里我们使用大O的渐进表示法。
就比如
当一个时间复杂度的函数表达式为F(N)=N*N+2*N+10时
- 当N=10的时候,结果为130
- 当N为100的时候,结果为10210
- 当N为1000的时候,结果为1002010
- 由此可以见,当N越来越大的时候,时间复杂度与N^2关系最大,函数表达式中其他值对其影响不大,故可以用O(N^2)来表示时间复杂度
大O的渐进表示法
大O符号(Big O notation):是用于描述函数渐进行为的数学符号。
推导大O阶方法:
1、用常数1取代运行时间中的所有加法常数。
2、在修改后的运行次数函数中,只保留最高阶项。
3、如果最高阶项存在且不是1,则去除与这个项目相乘的常数。得到的结果就是大O阶。
使用大O的渐进表示法以后,Func1的时间复杂度为:
N = 10 F(N) = 100
N = 100 F(N) = 10000
N = 1000 F(N) = 1000000
通过上面我们会发现大O的渐进表示法去掉了那些对结果影响不大的项,简洁明了的表示出了执行次数。
另外有些算法的时间复杂度存在最好、平均和最坏情况:
最坏情况:任意输入规模的最大运行次数(上界)
平均情况:任意输入规模的期望运行次数
最好情况:任意输入规模的最小运行次数(下界)
例如:在一个长度为N数组中搜索一个数据x
最好情况:1次找到
最坏情况:N次找到
平均情况:N/2次找到
在实际中一般情况关注的是算法的最坏运行情况,所以数组中搜索数据时间复杂度为O(N)
寻找大o渐进表达式的方式
计算时间复杂度,是需要分析和一定数学基础,我们来介绍几个常见的求时间复杂度的情景
1.一层循环
一层循环是相对简单的,它的计算时间复杂度的步骤主要有五步
1.找出趟数t,也就是操作执行次数,这是我们要求的时间复杂度,我们的目的就是构造它的函数,还有要找出每次操作执行时循环变量i的变化值
2.找出t和I的关系,构造二者的函数关系
3.确定循环停止条件,肯定与i有关
4.联立求解
例如
int fun(int n)
{
int i=1;
while(i<n)
i=i*2;
return i;
}
t=0,i=1
t=1,i=2;
t=2,i=2*2;
t=3,i=2*2*2;
........
t=n,i=2^n;
可得:i=2^t;
找出i与t的关系,我们在找循环的终止条件,可以发现,在i=n的时候,循环结束
于是有:n=2^t
可得:t=log2n
于是时间复杂度为O(log2n)
2.双层循环
1.列出外层循环中i的变化值
2.列出内层语句的执行次数
3.求和
双层循环和一层循环的求解差不多,但有些地方易错。
例如
int fun(int n)
{
int i=0;
int j=0;
for(i=0;i<n;i++)
{
for(j=0;j<n;i++)
{
}
}
}
这个例子很简单,外层循环n次,每一次外层循环需要进行n次内层循环,故执行次数就是n个n相加,简化为n方,故大o就是n^2,简单来说,就是外层循环执行次数乘内层循环执行次数。
但并非都是这样,具体情况具体分析
如
int fun(int n)
{
int i=0;
int j=0;
for(i=0;i<n;i++)
{
for(j=0;j<i;j++)
{
}
}
return 0;
}
t=0,i=0,j=0;
t=1,i=1,内层循环执行1次
t=2,i=2,内层循环执行2次,
t=3,i=3,内层循环执行3次
.......
t=n,i=n,内层循环执行n次
这里的i和t都可以看成趟数,一趟执行i次,一共n次,故执行次数是一个从0到n的等差数列求和,公差为1
列出关系式:n=t*(t+1)/2
得出:n=t^2+t,两边取平方根
得
故大o为根号n
很多嵌套循环,我们都可以用外层循环次数乘以内层循环次数求时间复杂度,这取决于内层循环次数是不是不变,如果内层循环固定,就可以直接使用内层循环乘外层循环次数。
对于多层循环,我们需要优先计算最底层循环的执行次数,在依次往外走,有时候是求和,有时候可以直接相乘,具体情况在具体分析,总之,我们熟练掌握一层循环的求时间复杂度步骤和双层循环的求复杂度模式,就可以对多层循环进行分析,找出关系式,求出结果。
求时间复杂度,可以抽象为求那个执行最多的操作的被执行次数.