时间复杂度:函数计算之行的基本次数
面试tip:面试官问及时间复杂度不一定只有最坏的,一般人一般会直接答最坏的,其实还有最好和平均。
例如:在一个长度为N的线性表中搜索一个数据x。
最坏:没有找到,到最后才找到
平均:不好不坏到中间才找到
最好:很开心第一下就找到了,一般必须要关注,但是在哈希的时候会关注
官方的说法:
- 最坏情况:任意输入规模的最大运行时间。(上界)
- 平均情况:任意输入规模的期望运行时间。
- 最好情况:任意输入规模的最小运行时间,通常最好情况不会出现。(下界)
在实际中我们通常情况考量的是算法的最坏运行情况。也就是说对于任意输入规模N,算法的最长运行时间,理由如下:
- 一个算法的最坏情况的运行时间是在任意输入下的运行时间上界。
- 对于某些算法,最坏的情况出现的较为频繁。
- 大体上看,平均情况与最坏情况一样差。
算法分析要保持大局观:
- 忽略掉那些的常数。
- 关注运行时间的增长趋势,关注函数式中增长最快的表达式。
描述这时间复杂度的站在数学家的角度总会抽象出一个东西,那这个东东我想就是大O的渐进表示法、
如:F(N) = N^3 + N^2 + N +1000,则关注N^3->O(N^3)
void Test1 ( int N )
{
for (int i = 0; i < N ; ++ i)
{
for (int j = 0; j < N ; ++ j)
{
//...
}
}
for (int k = 0; k < 2 * N ; ++ k)
{
//...
}
int count = 10;
while (count --)
{
//...
}
}
Test1的时间复杂度为:O(N^2)
void Test2 (int N, int M)
{
for (int i = 0; i < M ; ++i)
{
}
for (int k = 0; k < N ; ++k)
{
//...
}
}void Test3 (int N, int M)
{
for (int i = 0; i < M ; ++i)
{
for (int j = 0; j < N ; ++j)
{
//...
}
}
}
void Test3 (int N, int M)
{
for (int i = 0; i < M ; ++i)
{
for (int j = 0; j < N ; ++j)
{
//...
}
}
}
下面来算下常见的几种算法的时间复杂度:
冒泡:(比较次数)
等差数列:(n-1)+(n-2)+.......+1 = n*(1+(n-1))/2 = 1/2n^2 约等于 O(n^2)
二分查找:(前提:有序)相当于一颗搜索二叉树(左孩子比根大右孩子比根小),每次排出一半
假设树的高度h节点有N个
2^h-1 = N
二分查找的时间复杂度相当于搜索二叉树的高度 !!! 是不是很震撼
这里扩展下如果不是二分查找,三分,四分,五分呢? 那不就是多叉树吗!!哈哈
二分查找的时间复杂度:O(log2N)
变形下就是:O(logmN) (m就是几叉 几分)
折纸法理解折半查找
递归算法的时间复杂度计算
递归算法的时间复杂度为递归总次数*每次递归次数。
- 空间复杂度
空间复杂度的计算跟时间复杂度类似,也使用大O的渐进表示法。--(对象的个数)
要注意的是递归算法的空间复杂度,假如递归深度为N*每次递归的空间大小为1,则空间复杂度为O(N)。
- 以斐波那契数列学习时间复杂度&空间复杂度的计算
long long Fibonacci1( int n )
{
return n < 2 ? n : Fibonacci(n -
1) + Fibonacci( n - 2);
}
斐波那契递归算法时间复杂度:O(2^N)空间复杂度为:O(N)(请自己画图思考这里的时间复杂度和空间复杂度是这样?)
实现斐波那契数列
升级版1: 要求时间复杂度为O(N)。
升级版2:要求时间复杂复杂度为O(N),空间复杂度为O(1)。
斐波那契的优化
long long Fibonacci2(int n)
{
long long * fibArray = new long long[ n+1];
fibArray[0] = 0;
fibArray[1] = 1;
for (int i =
2; i <= n ; ++i)
{
fibArray[i ] = fibArray[ i -
1] + fibArray [i - 2];
}
long long ret = fibArray[n ];
delete[] fibArray ;
return ret ;
}
long long Fibonacci3( int n )
{
long long fibArray[3] = {0, 1, n};
for (int i =
2; i <= n ; ++i)
{
fibArray[2] = fibArray [1] + fibArray[0];
fibArray[0] = fibArray [1];
fibArray[1] = fibArray [2];
}
return fibArray [2];
}