1.基本概念
-
数据结构和算法本身解决的是“快”和“省”的问题
- 即如何让代码运行得更快如
- 何让代码更省存储空间
-
衡量标准
- 时间,空间复杂度分析
- 复杂度分析是整个算法学习的精髓
2.为什么需要复杂度分析?
-
事后统计法
-
通过统计、监控,就能得到算法执行的时间和占用的内存大小\
-
缺陷
-
测试结果非常依赖测试环境\
-
试结果受数据规模的影响很大\
-
-
-
我们需要一个不用具体的测试数据来测试,就可以粗略地估计算法的执行效率的方法\
3.大 O 复杂度表示法
-
算法的执行效率,粗略地讲,就是算法代码执行的时间
-
代码的每一行都执行着类似的操作:读数据(从内存读)-运算(在CPU中运算)-写数据(写入内存)
-
假设每行代码执行的时间都一样,为 unit_time
-
demo1
-
第 2、3 行代码分别需要 1 个 unit_time 的执行时间\
-
第 4、5 行都运行了 n 遍\
-
一共运行了(2n+2)*unit_time,所有代码的执行时间 T(n) 与每行代码的执行次数成正比
-
-
demo2
-
第 2、3、4 行代码,每行都需要 1 个 unit_time 的执行时间
-
第 5、6 行代码循环执行了 n 遍,需要 2n * unit_time 的执行时间\
-
第 7、8 行代码循环执行了 n2遍\
-
整段代码总的执行时间 T(n) = (2n2+2n+3)*unit_time\
-
-
//demo2 int cal(int n) {
int sum = 0;
int i = 1;
for (; i <= n; ++i) {
sum = sum + i;
}
return sum;
}
//demo2 int cal(int n) {
int sum = 0;
int i = 1;
int j = 1;
for (; i <= n; ++i) {
j = 1;
for (; j <= n; ++j) {
sum = sum + i * j;
}
}
}
-
可以看出代码的执行时间 T(n) 与每行代码的执行次数 f(n) 成正比
-
其中 T(n) 表示代码执行时间
-
n是数据规模大小
-
f(n) 表示每行代码执行的次数总和\
-
O正比系数
-
时间复杂度表示法\
-
代码执行时间随数据规模增长的变化趋势
-
-
-
全称:渐进时间复杂度(表示算法的执行时间与数据规模之间的增长关系)
\
4.时间复杂度分析
-
时间复杂度分析小技巧(只关注复杂度最高的代码)
-
只关注循环执行次数最多的一段代码(忽略掉公式中的常量、低阶、系数即可)\
-
加法法则:总复杂度等于量级最大的那段代码的复杂度\
- 已知复杂度(例如100次),属于常数级
-
乘法法则:嵌套代码的复杂度等于嵌套内外代码复杂度的乘积\
-
-
常见时间复杂度实例分析
-
多项式量级\
-
O(1) 常量级时间复杂度(只要代码的执行时间不随 n 的增大而增长)\
-
O(logn)、O(nlogn) \
-
所有对数阶的时间复杂度都记为 O(logn)\
-
执行n遍的O(logn)=O(nlogn) 归并排序 快速排序
-
-
O(m+n)、O(m*n) 有两个不确定的数据规模\
-
-
非多项式量级(即NP问题)(随着问题规模的增加,时间会无限增长,是非常低效的算法)\
-
O(2n)\
-
O(n!)\
-
-
//对阶时间复杂度 i=1; while (i <= n) { i = i * 2; }
5.空间复杂度分析
-
渐进空间复杂度,表示算法的存储空间与数据规模之间的增长关系\
-
空间复杂度就是
-
O(1)
-
O(n)
-
O(n2 )\
-
O(logn)、O(nlogn)几乎很少用到\
-
6.总结
-
复杂度也叫渐进复杂度,包括时间复杂度和空间复杂度\
-
时间复杂度:分析算法执行效率
-
空间复杂度:数据规模大小\
-
复杂度类型:O(1)、O(logn)、O(n)、O(nlogn)、O(n2 )