基本知识
1、时间频度
一个算法中的语句执行次数叫做语句频度或时间频度,用T(n)表示。理论上无法计算一个算法执行所需的时间,必须上机测试才能知道,但是我们不可能也没必要对每个算法都进行上机测试,我们只需要知道哪个算法运行时间长,哪个算法运行时间短即可。算法花费的时间和算法中语句执行次数成正比,哪个算法中语句执行次数多,花费时间就长,所以我们只需要知道语句执行次数就可以知道算法大致的执行时间。
2、时间复杂度
问题规模用n表示,当n不断变化时,时间频度T(n)也会发生变化,我们并不关注某个问题规模的时间频度,而是想知道时间频度随着问题规模n的变化呈现怎样的变化趋势,因此提出了时间复杂度概念。算法中基本操作重复执行次数是n的某个函数,记为T(n),当n趋于无穷大的时候,如果T(n)/f(n)无限接近非零数,我们就称T(n)和f(n)是同数量级函数,记作T(n)=O(f(n)),称O(f(n))是算法的渐进时间复杂度,简称时间复杂度。本质上,时间复杂度是时间频度的同阶无穷小,即时间复杂度=O(时间频度),而上式中的f(n)其实就是算法中频度最大的语句频度。不同的时间频度,有可能对应相同的时间复杂度。比如,T(n)=2n^2和T(n)=4n^2,虽然二者的时间频度不同,但时间复杂度都是O(n^2)。
时间复杂度关注的是随着问题规模n的变化(比如线性变化),算法运行时间会呈什么样的趋势变化,有的不会变,有的线性变化,有的指数变化。比如问题规模从n变到2n,如果运行时间也是线性变化,那么就是线性复杂度,如果运行时间指数变化,那么就是指数复杂度。
常见的时间复杂度有:常数阶O(1)、对数阶O(log2n)、线性阶O(n)、线性对数阶O(nlog2n)、平方阶O(n2)、立方阶O(n3)、...、k次方阶O(n^k)、指数阶O(2^n)等。
一般我们说的时间复杂度就是最坏时间复杂度,即最坏情况下的时间复杂度,是所有输入实例的上届,这样就能保证算法的运行时间不会比最坏时间复杂度下的时间长。平均时间复杂度是指所有可能的输入实例均以等概率出现的情况下,算法的期望运行时间。
3、空间复杂度
空间复杂度是指运行完一个程序所需的内存大小。利用空间复杂度,我们可以预估运行所需内存。包括两部分,固定部分和可变部分。
固定部分:指令空间(代码空间)、数据空间(常量、简单变量)等所占的空间,与输入/输出数据的个数大小数值无关,属于静态空间。
可变部分:与具体算法有关,包括动态分配的空间,以及递归栈所需的空间等。假设算法所需的存储空间是f(n),那么算法空间复杂度是O(f(n))。
设计算法时,我们要考虑算法的时间复杂度和空间复杂度,目的在于,要知道随着问题规模的变化,算法运行时间和空间会以怎样的趋势变化。复杂度越小,运行时间越快,占用空间越小,这也是算法设计的目标。
排序算法复杂度比较
此图来源于网络。