时间复杂度和空间复杂度是算法分析的重要内容,判断一个算法的优劣程度、评价算法是否可行,都需要考虑这两个指标的大小。
1,时间复杂度
时间复杂度(Time Complexity):用来描述算法的执行时间,也就是代码运行的时间。通常用“大 O 记法”(Big O Notation)表示,表示算法执行时间与问题规模之间的增长关系,即在最坏情况下,算法执行的时间复杂度是多少。时间复杂度越小,算法的效率就越高。
注意O(1+3n)=O(n),因为只计算n趋于无限大的情况,1可以省略。常见的时间复杂度量级如下:
- 常数阶O(1)
- 对数阶O(logN)
- 线性阶O(n)
- 线性对数阶O(nlogN)
- 平方阶O(n²)
- 立方阶O(n³)
- K次方阶O(n^k)
- 指数阶(2^n)
- 阶乘O(n!)
2,空间复杂度
空间复杂度(Space Complexity):通常用来描述算法所占用的内存空间大小。空间复杂度也是用大O记法表示,是对一个算法在运行的过程中临时占用存储空间大小的量度。空间复杂度越小,算法所需的内存空间就越少。
比较常用的空间复杂度有:O(1)、O(n)、O(n²)。在下面的例子中,我们用 S(n) 来定义「空间复杂度」。
O(1)空间复杂度
如果算法执行所需要的临时空间不随着某个变量n的大小而变化,此算法空间复杂度为一个常量,可表示为 O(1):
int x = 0;
int y = 0;
x++;
y++;
其中x, y所分配的空间不随着处理数据量变化,因此「空间复杂度」为 O(1)
O(n)空间复杂度
int[] newArray = new int[n];
for (int i = 0; i < n; i++) {
newArray[i] = i;
}
3,速查表
3.1 抽象数据
3.2数组排序
4举例
以最简单的二分法找到所要求的数字为例:
假如有一列数列:上方是数,下方是index
13 | 25 | 34 | 45 | 55 | 66 | 76 | 81 | 99 | 100 |
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
我们要在里面找到99这个数,那么可以使用二分法首先定位0-9中间的数,这里特殊举了偶数的例子,可以选取中间两个数的平均数作为基准点,然后根据比较结果选择进一步搜索左半部分或右半部分。具体来说,可以先通过整除运算获得中间位置的下标mid,然后再根据mid的奇偶性进行处理:
- 如果mid为奇数,则中间位置只有一个元素,直接以该元素为基准点进行比较
- 如果mid为偶数,则中间位置有两个元素,可以选择左边那个元素或者右边那个元素作为基准点进行比较
以右边为基准点,那么过程就是:
定位:5比较66<99
定位:7比较81 <99
定位:8比较99=99|
找到啦。
这就是一个简单的二分法找数字的算法。那么这个算法是时间复杂度怎么算呢?
时间复杂度:
加入我们算了k次,数列长度为n,那么我们算的过程就是:
最糟糕的情况是
也就是我们找了k次只剩下一个元素,也就是我们要的元素,那么这种情况下k等于多少呢?
因此时间复杂度就是
二分法的空间复杂度:
二分法的空间复杂度是O(1),也就是常数级别的空间复杂度。
其原因是二分法算法只需要用到一个中间变量来记录中间位置,同时对原序列进行直接读取和比较操作,不需要额外的空间来存储数据。
因此,无论被搜索序列的大小如何,算法所需要的额外空间都是固定的,与问题规模无关,因此其空间复杂度是常数级别的。