一.时间复杂度
思考一下我们如何评估算法时间开销呢?
我们可以让算法先运行,事后统计。但是会出现以下几个问题:
1.不同机器的性能不同
2.编程语言不同,越高级越慢
3.一些算法不能事后统计
4.和编译程序产生的机器指令质量有关
所以我们需要事前预估。引入时间复杂度
实际上就是时间开销T(n)与问题规模n的关系
上述代码中:
1执行了1次
2执行3001次
3执行3000次
4执行1次
所以:T(3000)= 1+3001+2*3000+1
转换为表达式为T(n)=3n+3
思考这个问题:如果表达式中有高次我们怎么处理?是否可以忽略表达式某一部分?
答案是肯定的
如果出现高次,我们只取最高项,并且也忽略这一项的系数
我们用大O表示同阶,同等数量级。
所以我们表达式可以简化为:T= O(n),T=O(n²)……
函数举例 | 阶 | 阶数 |
---|---|---|
12 | O(1) | 常数阶 |
2n+3 | O(n) | 线性阶 |
3n2+2n+1 | O(n2) | 平方阶 |
5log2n+20 | O(logn) | 对数阶 |
2n+3nlog2n+19 | O(nlogn) | nlogn阶 |
6n3+2n2+3n+4 | O(n3) | 立方阶 |
2n | O(2n) | 指数阶 |
消耗时间顺序:常对线,幂指阶
O(1) < O(log2n) < O(n) < O(nlog2n) < O(n2) < O(n3) < O(2n) < O(n!) < O(nn)
多层嵌套时,分析最深层的
二.常用技巧:
加法规则:O(f(n)) + O(g(n)) = O(max(f(n),g(n)))
乘法规则:O(f(n)) * O(g(n)) = O(f(n)*g(n))
三种复杂度
假设有一个从1到n乱序的数组。
一个循环从数组第一个元素查找元素n。会出现下面三种情况:
最坏时间复杂度:n在最后一个位置
平均时间复杂度:n在任意位置,概率1/n,循环次数x= (1+2+3+…+n)1/n=(n*(1+n)/2)*1/n=(1+n)/2
最好时间复杂度:n在第一个位置
可以看出算法执行时间可能与输入的数据有关