时间复杂度
一、时间复杂度的基本概念
1.时间复杂度
问题实例是决定计算成本的主要因素,具体地,特定算法处理规模为n的问题所需的时间可记为T(n)
T(n)是算法所执行基本操作的总次数,决定于组成算法的所有语句各自的执行次数,以及其中所含基本操作的数目。
2.渐进复杂度
评价算法效率时,关注其处理大规模问题时的表现,着重长远、更为注重时间复杂度的总体变化趋势和增长速度的策略和方法,即渐进分析。
3.不同记法
(1)“大O记号”——渐进上界(读法:big O)
T(n)= O(f(n))
c>0,有O(f(n))= O(c*f(n))
a>b>0,有O(n^a+n^b) = O(n^a)
(2)“大Ω记号”——渐进下界(读法:big omega)
(3)“大Θ记号”——确界(读法:big theta)
二、时间复杂度的分析
1.常数O(1)
include<iostream>;
using namespace std;
int sum = 0,n = 100; //执行一次
sum = (1+n)*n/2; //执行一次
std ::cout<<sum; //执行一次
运行次数的函数为f(n) = 3,推导大O阶的规则,需要将3变为1,所以T(n)=3,所以算法复杂度为O(1)
2. 线性阶
主要分析循环结构的运行情况,
for(int i = 0;i<n; i++)
{
//时间复杂度为O(1)的算法
...
}
上面循环体中的代码执行了n次,因此时间复杂度为O(n)
3.对数阶
int num = 1;
while (num < n)
{
num = num *2;
//时间复杂度为O(1)的算法
}
设循环次数为x,2^x=n,s所以x=log2n
所以时间复杂度为O(logn)
4.平方阶
循环嵌套
for(int i = 0; i<n ; i++)
{
for(int j =i; j<n ; j++)
{
//复杂度为O(1)的算法
}
}
内循环中j从i开始增加,直到n,因此循环次数为n+(n-1)+(n-2)+...+1 = n(n+1)/2 = n^2 + n/2
由于大O阶只保留最高阶,且忽略常数,所以T(n)=O(n^2)
5.比较
O(1)<O(logn)<O(n)<O(nlogn)<O(n^2)<O(n^3)<O(2^n)<O(n!)
因此,一般而言,算法的时间复杂度尽量为O(1)、 O(logn) 、O(n)、 O(nlogn)且越小越好