第一次写博文,侵删并见谅
以下开始正文
为什么需要复杂度分析
把代码跑一遍,通过统计、监控,就能得到算法执行的时间和占用的内存大小,而且是非常精准的,那为什么还要做时间、空间复杂度分析呢?
原因有二:
- 测试结果非常依赖测试环境:
例如同样的代码在 i9 和 i3 上跑的时间会不一样 - 测试结果受数据规模的影响很大:
小规模数据 情况下 插入排序O(n²) 可能比 快速排序O(nlogn) 还要快
结果:
我们需要一个不用具体的测试数据来测试,就可以粗略地估计 算法的执行效率的方法. 这就是我们今天要讲的时间、空间复杂度分析方法。
大O复杂度表示法
例1.
1. int cal(int n) {
2. int sum = 0;
3. int i = 1;
4. for (; i <= n; ++i) {
5. sum = sum + i;
6. }
7. return sum;
8. }
我们假设每行代码执行的时间为unit-time
第2、3行代码分别需要1个unit_time的执行时间,
第4、5行都运行了n遍, 所以需要2n*unit_time,
所以这段代码执行的时间就是T(n) = (2n+2)*unit_time。
例2.
1. int cal(int n) {
2. int sum = 0;
3. int i = 1;
4. int j = 1;
5. for (; i <= n; ++i) {
6. j = 1;
7. for (; j <= n; ++j) {
8. sum = sum + i * j;
}
}
}
我们依然假设每行代码执行的时间为unit-time
第2、 3、 4行代码,每行都需要1个unit_time的执行时间
第5、 6行代码循环执行了n遍,需要2n * unit_time的执行时间
第7、 8行代码循环执行了n2遍,所以需要2n2 * unit_time的执行时间
所以,整段代码总的执行时间T(n) = (2n2+2n+3)*unit_time
注意,大O就要登场了
T
(
n
)
=
O
(
f
(
n
)
)
T(n) = O(f(n))
T(n)=O(f(n))
- T(n)表示代码执行的时间
- n表示数据规模
- f(n)表示每行代码执行的次数总和
大O时间复杂度实际上并不具体表示代码真正的执行时间, 而是代码执行时间随数据规模增长的变化趋势, 所以也叫作渐进时间复杂度, 简称时间复杂度。
低阶、常量、系数三部分并不左右增长趋势,所以例1的T(n) = O(n), 例2的T(n) = O(n2)
时间复杂度分析
三个实用方法:
-
只关注循环执行次数最多的一段代码
例1和例2 -
加法法则
-
乘法法则