如何衡量一个算法的好坏?
算法的好坏由算法效率决定.算法效率分析分为两种:第一种是时间效率,第二种是空间效率。时间效率被称为时间复杂度
而空间效率被称作空间复杂度. 时间复杂度主要衡量的是一个算法的运行速度,所以时间复杂度越大说明运算效率越差
什么是时间复杂度?
一个算法所花费的时间与其中语句的执行次数成正比,算法中的基本操作的执行次数,为算法 的时间复杂度
时间复杂度为什么不使用时间而使用基本语句的运行次数衡量?
一个算法执行所耗费的时间,从理论来说是不能人为计算出来的,因为程序需要在电脑上运行才能计算时间,使用基本语句的运行次数来衡量是因为算法执行所花费的时间与其中语句的执行次数成正比
时间复杂度的O渐进表示法
实际中我们计算时间复杂度时,我们其实并不一定要计算精确的执行次数,而只需要大概执行次数,那么这里我们使用大O的渐进表示法
大O符号(Big O notation):是用于描述函数渐进行为的数学符号
推导大O阶方法:
<1>、用常数1取代运行时间中的所有加法常数
<2>、在修改后的运行次数函数中,只保留最高阶项
<3>、如果最高阶项存在且不是1,则去除与这个项目相乘的常数。得到的结果就是大O阶
时间复杂度的:最优、平均、最差情况,为什么时间复杂度看的是最差情况?
<1>、最坏时间复杂度,是在任意输入下的运行时间界限,保证算法任何时候运行时间都不会比其更长
<2>、在某些算法上,最坏情况出现频繁
<3>、在算法这样的事物上,平均和最坏一样很糟糕
如何求解:二分查找、递归求阶乘、递归斐波那契的时间复杂度?
先推导出二分查找的数学表达式,二分查找中元素的个数变化为N/2/2/2...../2=1,直至元素个数为1时被找到,将/2的次数设为M次,进行数学变形得到1 * 2 * 2 * 2....=N, M=logN ,所以二分查找的时间复杂度为O(lgN)
递归函数时间复杂度的计算公式 : 一条基本语句在单次递归函数中执行的次数 * 递归函数递归的总次数
什么是空间复杂度?
空间复杂度是对一个算法在运行过程中临时占用存储空间大小的量度
如何求空间复杂度? 普通函数&递归函数
空间复杂度计算的是变量的个数,没有借助辅助空间,空间复杂度就是O(1),动态开辟N个空间,空间复杂度就是O(N)
递归函数调用了N次,就开辟了N个栈帧,空间复杂度就是O(N)
分析递归斐波那契数列的:时间、空间复杂度,并对其进行优化,伪递归优化—>循环优化
常见写法:
long long fib(long long x)
{
if (x<3)
{
return 1;
}
return fib(x - 1) + fib(x - 2);
}
首先找出一条基本语句,if (x<3),这条语句每次递归都会调用,现在只需要求出递归次数即可
递归次数求解如图:
根据公式计算1( 2^0 + 2^1+…+2 ^n-3),结果为 2^n-4, 用大O的渐进表示为O(2^N)*
对其进行伪递归优化:
long long Fib(long long n,long long first,long long second)
{
if (n < 3)
{
return second;
}
if(n==3)
{
return first + second;
}
return Fib(second, first + second, n - 1);
}
递归次数求解如图:
根据公式计算 1(n-3),用大O的渐进表示法表示为O(N)*
对其进行循环优化:
long long fib(long long x)
{
if x<3)
{
return 1;
}
int last3 = 1;//倒数第三项
int last2 = 1;//倒数第二项
int a=0;//最后一项
for (int n = 3; n <= x; ++n)
{
a = last3 + last2;//最后一项等于前两项之和
last3 = last2;//新的倒数第三项
last2 = a;//新的倒数第二项
}
return a;
}
基本语句选择if x<3)每次循环都会执行这一条语句,循环总共执行x-2次,所以循环优化的时间复杂度为O(N)
总结常见时间复杂度
常见时间复杂度有 : O(1),O(N),O(N^2), O(N^3), O(lgN),O(2^N)