时间复杂度的概念
在计算机科学中,时间复杂度是一个函数,它定量描述了该算法的运行时间,一个算法执行所耗费的时间,从理论上说,是不能算出来的,只有把你的程序放在机器上跑起来,才能知道。但是我们需要每个算法都上机测试吗?是可以都测试,但是这很麻烦,所以有了时间复杂度这个分析方式,一个算法所花费的时间于其中语句的执行此数成正比例,算法中的基本操作的执行次数为算法的时间复杂度。
即:找到某条基本语句与问题规模N之间的数学表达式,就是算出了该算法的时间复杂度。
嵌套循环时间复杂度计算
void fun(int N)
{
int count=0;
for(int i=0;i<N;i++)
{
for(int j=0;j<N;J++)
{
count++;
}
}
for(int k=0;k<2*N;k++)
{
count++;
}
int M=6;
while(M--)
{
count++;
}
print("%d\n",count);
}
时间复杂度的函数式
F(N)=N*N+2*N+6
实际中我们计算时间复杂度时,我们其实并不一定要计算精确的执行次数,而只需要大概执行次数,那么这时我们使用大O的渐进表示法(估算)。
即:O(N^N)
大O的渐进表示法
大O符号(Big O notation):用于描述函数渐进行为的数学符号。
常见推导大O阶方法:
1.用常数1取代运行时间中所有加法常数
示例:
int fun(int N)
{
int count=0;
for(int i=0;i<10;i++)
{
count++;
}
return count;
}
时间复杂度:O(1)
2.在修改后的运行次数函数中,只保留最高阶项
示例:
void fun(int N;int M)
{
int count=0;
for(int i=0;i<N;i++)
{
count++;
}
for(int j=0;j<M;j++)
{
count++;
}
printf("%d",count);
}
1.N和M相差不大,时间复杂度为O(N+M)
2.N>>M,时间复杂度为O(N)
3.N<<M,时间复杂度为O(M)
3.如果最高阶项存在且不是1,则去除与这个项目相乘的常数。得到的结果就是大O阶
示例:
int fun(int N)
{
int count=0;
for(int i;i<N*2;i++)
{
count++;
}
return count;
}
时间复杂度为O(N)
strchr的时间复杂度(可变)
const char* strchr(const char* str ,int character)
{
while(*str)
{
if(*str==charater)
return str;
else
str++;
}
}
最坏情况:任意输入规模的最大运行次数(上界)
平均情况:任意输入规模的期望次数
最好情况:任意输入规模的最小运行次数(下届)
例如:在一个长度为N数组中搜素一个数据x
最好情况:1次找到
平均i情况:N/2次找到
最坏情况:N次找到
在实际中一般情况关注的是算法的最坏运行情况,所以数组中搜索时间复杂度为O(N)
冒泡排序的时间复杂度
void bublle_sort(int arr[],int N)
{
for(int i=0;i<N-1;i++)
{
for(int j=0;j<N-i-1;j++)
{
if (arr[j]=arr[j+1])
{
int tmp;
tmp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=tmp;
}
}
}
}
时间复杂度为O(N^2)
二分查找的时间复杂度
int BinarySearch(int *a ,int N,int x)
{
assert(a);
int begin=0;
int end=N;
while(begin<end)
{
int mid=begin+((end-begin)>>1);
if (a[mid]<x)
begin=mid+1;
else if (a[mid]>x)
end=mid;
else
return mid;
}
return -1;
}
N/2/2/2/.../2=1
2^x=N
复杂度=O(log2N)
斐波那契数列的时间复杂度
long long Fib(size_t N)
{
if(N<3)
return 1;
else
return Fib(N-1)+Fib(N-2);
}
时间复杂度为:O(2^N)
时间复杂度要根据实际的函数来计算,结合图像来找思路。