要谈时间复杂度与空间复杂度,需要先了解,他们影响了什么。这里我们引出算法效率。
一、时间复杂度
1.1 概念
时间复杂度是同一问题可用不同算法解决,而一个算法的质量优劣将影响到算法乃至程序的效率。算法分析的目的在于选择合适算法和改进算法。
计算机科学中,算法的时间复杂度是一个函数,它定性描述了该算法的运行时间。这是一个关于代表算法输入值的字符串的长度的函数。时间
复杂度常用大O符号表述,不包括这个函数的低阶项和首项系数。使用这种方式时,时间复杂度可被称为是渐近的,它考察当输入值大小趋近无
穷时的情况。
1.2 渐进表示法
// 请计算一下Func1基本操作执行了多少次?
void Func1(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;
Func1 执行的基本操作次数 :
推导大O阶方法:
1、用常数1取代运行时间中的所有加法常数。
2、在修改后的运行次数函数中,只保留最高阶项。
3、如果最高阶项存在且不是1,则去除与这个项目相乘的常数。得到的结果就是大O阶。
1.3 实例
实例1:
// 计算BinarySearch的时间复杂度?
int BinarySearch(int* a, int n, int x)
{
assert(a);
int begin = 0;
int end = n-1;
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;
}
实例1基本操作执行最好1次,最坏O(logN)次,时间复杂度为 O(logN) ps:logN在算法分析中表示是底数为2,对数为N。有些地方会写成lgN。
实例2:
// 计算阶乘递归Factorial的时间复杂度?
long long Factorial(size_t N)
{
return N < 2 ? N : Factorial(N-1)*N;
}
实例2通过计算分析发现基本操作递归了N次,时间复杂度为O(N)。
实例3:
// 计算斐波那契递归Fibonacci的时间复杂度?
long long Fibonacci(size_t N)
{
return N < 2 ? N : Fibonacci(N-1)+Fibonacci(N-2);
}
实例3通过计算分析发现基本操作递归了2^N次,时间复杂度为O(2^N)。
二、空间复杂度
2.1 概念
空间复杂度(Space Complexity)是对一个算法在运行过程中临时占用存储空间大小的量度,记做S(n)=O(f(n))。比如直接插入排序的
时间复杂度是O(n^2),空间复杂度是O(1) 。而一般的递归算法就要有O(n)的空间复杂度了,因为每次递归都要存储返回信息。一个
算法的优劣主要从算法的执行时间和所需要占用的存储空间两个方面衡量。
2.2 实例分析
实例1:
// 计算Fibonacci的空间复杂度?
long long* Fibonacci(size_t n)
{
if(n==0)
return NULL;
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];
}
return fibArray ;
}
解析:
实例1动态开辟了N个空间,空间复杂度为 O(N)
实例2:
// 计算阶乘递归Factorial的时间复杂度?
long long Factorial(size_t N)
{
return N < 2 ? N : Factorial(N-1)*N;
}
解析:
实例2递归调用了N次,开辟了N个栈帧,每个栈帧使用了常数个空间。空间复杂度为O(N)
这篇博客主要讲解了数据结构中,算法效率分析中的两个关键点,时间和空间复杂度。