写在之前
在学习算法之前,应该了解什么是算法复杂度,它包括时间复杂度【时效】和空间复杂度【存储】,用于衡量一个算法的好坏;
对于同一个问题来说,可以有多种解决问题的算法,不同方法会有不同的复杂度,我们总是希望既快占用内存又小的算法。所以好的算法应该具备时效高和存储低的特点。
时间复杂度
设问题的规模为n,基本操作重复执行的次数是问题规模n的某个函数,记为f(n),
则算法的时间量度可以记为:T(n) = O(f(n))。
一些函数
在我们之后的算法学习过程中,会遇到各种各样的数量级函数,下面我给大家列举几种常见的数量级函数:
为了确定这些函数哪些在 T(n) 中占主导地位,就要在 n 增大时对它们进行比较,请看下图(图片来自于 Google 图片):
总结:O(1) < O(logn) < O(n) < O(nlogn) < O(n^2) < O(n^3) < O(2^n)<O(n!)
计算时间复杂度
上面通过文字和图表的方式讲解了几种函数,那么如何计算时间复杂度呢?
一般地容易计算的方法是:看看有几重for循环,只有一重则时间复杂度为O(n),二重则为O(n^2),依此类推,如果有二分则为O(logn),二分例如快速幂、二分查找,如果一个for循环套一个二分,那么时间复杂度则为O(nlogn)。
例子:
数据量低时,O(1) 和 O(n^2)的区别可以忽略不计。比如,你有个算法要处理2000条元素。
O(1) 算法会消耗 1 次运算
O(log(n)) 算法会消耗 11 次运算
O(n) 算法会消耗 2000 次运算
O(n*log(n)) 算法会消耗 22,000 次运算
O(n^2) 算法会消耗 4,000,000 次运算
O(1) 和 O(n^2) 的区别似乎很大(4百万),但你最多损失 2 毫秒,只是一眨眼的功夫。确实,当今处理器每秒可处理上亿次的运算。这就是为什么性能和优化在很多IT项目中不是问题。
但是面对海量数据时,了解这个概念依然很重要。如果这一次算法需要处理 1,000,000 条元素(这对数据库来说也不算大)。
O(1) 算法会消耗 1 次运算
O(log(n)) 算法会消耗 20 次运算
O(n) 算法会消耗 1,000,000 次运算
O(n*log(n)) 算法会消耗 20,000,000 次运算
O(n^2) 算法会消耗 1,000,000,000,000 次运算
这下差距就大了,如果在数据规模更大点,那就。。。
空间复杂度
一个算法的空间复杂度是指该算法所耗费的存储空间,计算公式计作:S(n) = O(f(n))。其中 n 也为数据的规模,f(n) 在这里指的是 n 所占存储空间的函数。
然而现代计算机的存储一般都比较大,所以实际编程中大多不用去考虑空间问题;同时我们在日常写代码的时候衍生出了用「空间换时间」的做法,并且成为常态。比如我们在求解斐波那契数列数列的时候我们可以直接用公式去递归求,用哪个求哪个,同样也可以先把很多结果都算出来保存起来,然后用到哪个直接调用,这就是典型的用空间换时间的做法,具体哪种更好,需要具体问题具体分析。