1.2.1 算法的基本概念
算法:对特定问题求解步骤的一种描述,它是指令的有限序列,其中的每条指令表示一个或多个操作。
算法的五个重要特性
“好”的算法的五个目标
1.2.2 算法效率的度量
一、时间复杂度
算法的时间复杂度是指一个算法每行语句执行次数的最大值。
例子
运行结果
我们可以看到最终的运行次数取决于循环语句的运行次数,而循环语句的执行次数又与n有关,如果n的值无限大,那么循环的运行次数就会无限大,也就是n,所以运行时间复杂度就是n。
例子源代码(C语言)
#include <stdio.h>int main()
{//初始化;int i = 0;//运行了1次!//定义n的值;int n = 10;//运行了1次!//定义循环;for (i = 1; i <= n; i++)//运行了11次!{//打印现在是第几次运行;printf("现在是第%d次运行!", i);//运行了10次!//换行;printf("\n");//运行了10次!}//换行;printf("\n");//运行了1次!//打印总共运行了几次;printf("总共运行了%d次!", i);//运行了1次!return 0;
}
(一)时间复杂度的分类
1.常数阶O(1)
无伦代码执行了多少行,只要没有循环时间复杂度就为O(1)
2.线性阶O(n)
有循环,循环的时间复杂度为O(n)
3.对数阶O(logN)
从上面的代码中可以看到每次i的变化是乘2,所以相当于i乘2的x次方等于n,所以x等于log₂n。
所以时间复杂度为O(log₂n)
4.线性对数阶O(nlog₂n)
就是把对数阶循环n遍,时间复杂度就是O(nlog₂n)。
5.平方阶O(n²)
就是把循环n次再循环n次,时间复杂度为O(n²)。
6.立方阶O(n³)、K次方阶O(n^k)
参考上面的O(n²) 去理解就好了,O(n³)相当于三层n循环,其它的类似。
(二)循环语句的运算方法
以下面的代码为例
运算步骤
①找循环条件:n>=i*i;
②找循环体中的趋近条件结束变量:x=x+1;
③假设循环执行t次;
④将③带入②,计算t<=n的表达式;
③带入②:x=t
②带入①:n>=t²
n½>=t
t<=n½
算法的时间复杂度T(n)=O(n½)
(三)时间复杂度的不同情况
最坏时间度复杂度:在最坏的情况下算法的时间复杂度;
(比如找找一个数据,最坏情况就是把所有数据都查完了最后一个才是要找的数据)
平均时间复杂度:所有可能输入实例在等概率情况下,算法的期望运行时间;
(比如找找一个数据,平均情况就是在所有数据中位于中间位置的就是要查找的数据)
最好时间复杂度:在最好情况下算法的时间复杂度;
(比如找找一个数据,最好情况就是把第一个数据就是要查找的数据)
(四)常见的渐进时间复杂度
O(1) < O(log₂n) < O(n) < O(nlog₂n) < O(n²) < O(n³) < O(2ⁿ) < O(n!) < O(nⁿ)
二、空间复杂度
算法的空间复杂度为该算法在运行过程中所需要的存储空间。
(一)算法空间复杂度O(1)
如果算法执行所需要的临时空间不随着某个变量的大小而变化,即此算法空间复杂度为一个常量,可表示为 O(1)。
(二)算法空间复杂度O(n)
在上面的代码中数组a需要开辟的存储空间为n,在运行过程中循环只是往开辟好空间的数组a中不断填入数据,所以空间复杂度为O(n)。