通常咱们在选择算法时,都是想要选择效率最高的算法。那算法的效率,用什么表示?没错!就是用大O表示法。html
PS: 大O表示法中,log即为log2,后面再也不说明。java
下面以简单查找和二分查找,在含有n个元素的有序列表中查找其中一个元素为例,下表总结了咱们发现的状况。python
使用简单查找时,最多须要猜想次数与列表长度相同,这被称为线性时间,大O表示法为O(n)。mysql
二分查找则不一样,最多须要猜想次数为logn(n为列表长度),这被称为对数时间(log时间),大O表示法为O(logn)。面试
大O表示法指出了算法的速度有多快。算法
可能你会好奇,它的单位是多少?秒?没有单位,它并不是指的是时间,而是从增量的角度衡量。sql
列表中查找元素,简单查找、二分查找的增速以下图。数组
倘若咱们不知道增速,只知道查找100个元素时的查找时间,猜想10000个元素时的查找时间:学习
对于简单查找,100个元素时为100毫秒,简单推算出10000个元素为10秒;.net
对于二分查找,100个元素时为7毫秒,简单推算出10000个元素为700毫秒。
PS:简单推算 10000个元素时的运行时间= 运行时间(100个元素时)* 100
简单查找的推算是对的,由于的增速是n,而二分查找的推算是错的,它的增速为logn,这便不能理所固然简单推算了。
很显然,咱们只要知道算法的增速,便能知道它在n个元素中运行的运行时间了,大O表示法就是用来表示算法增速的。
专业描述:大O表示法表示操做数的增速,指出了算法运行时间的增速。
O(㏒n) 对数时间 好比二分查找
O(n) 线性时间 好比简单查找
O(n*㏒n) 好比快速排序
O(n²) 好比选择排序
O(n!) 好比旅行者问题
上述的大O表示法都是用来表示时间复杂度,并且一般指的是最坏状况下的时间复杂度。
一般有如下3种时间复杂度:
以简单查找为例子,在n个元素的列表中查找目标元素
最好状况时间复杂度:目标元素恰好在列表第一个位置,那么只须要一次就能找到,时间复杂度为O(1)。
最坏状况时间复杂度:目标元素在列表最后一个位置或者不在列表中,那么得须要遍历完整个列表才能得出结果,时间复杂度为O(n)。
平均状况时间复杂度:考虑目标元素在列表中任何位置的状况。
下面简单分析下:目标元素若是在列表中,出现的位置有n种状况,加上不在列表中这一种状况,总共n+1种状况。每种状况下须要遍历的次数以下表:
目标元素所在位置 | 遍历次 |
---|---|
第1个位置 | 1 |
第2个位置 | 2 |
第3个位 | 3 |
第n个位置 | n |
不在列表中 | n |
平均遍历次数=各类状况遍历次数相加÷总的状况数
各类状况遍历次数相加为**((1+2+3...+n)+n),总的状况数(n+1)**
平均状况复杂度为:
((1+2+3...+n)+n)/(n+1)=n(n+3)\2(n+1)
大O表示法,会省略系数、低阶、常量,因此平均状况时间复杂度是O(n)。
空间复杂度是对一个算法在运行过程当中临时占用存储空间大小的一个量度,反映的是一个趋势。
空间复杂度比较经常使用的有:O(1)、O(n)、O(n²),咱们下面来看看:
空间复杂度 O(1)
若是算法执行所须要的临时空间不随着某个变量n的大小而变化,即此算法空间复杂度为一个常量,可表示为 O(1)。
例子:
int i = 1; int j = 2; ++i; j++; int m = i + j;
i、j、m 所分配的空间都不随着处理数据量变化,所以它的空间复杂度 O(1)。
空间复杂度 O(n)
int[] m = new int[n] for(i=1; i<=n; ++i) { j = i; j++; }
第一行new了一个长度为n的数组m,占用大小为n,后面虽然有循环,但没有再分配新的空间,所以,这段代码的空间复杂度主要看第一行便可,即O(n)。
PS:O(n²)的异同,再也不累述。
如下常见排序算法的复杂度分析,感觉一下时间复杂度和空间复杂度。
参考:《算法图解》
http://www.javashuo.com/article/p-rjlsbijy-kb.html
http://www.javashuo.com/article/p-faouqvgr-no.html
文章首发于公众号【KEN DO EVERTHING】 本公众号专一于java相关技术,但不限于java、mysql、python、面试技巧、生活感悟等。分享优质博文,技术干货,学习资源等优质内容。 欢迎关注,一块儿学习,共成长!