时间复杂度
大O表示法
1 | int cal(int n) |
一行代码执行的时间为unit_time
第4行第5行分别执行了n遍,所以是 2*n unit_time
T(n) = O(f(n))
T(n)表示代码执行的时间;n表示数据规模的大小;f(n)表示每行代码执行的次数总和。因为这是一个公式,所以用f(n)来表示。公式中的O,表示代码的执行时间T(n)与f(n)表达式成正比。
时间复杂度分析
- 只关注执行次数最多的一段代码
- 加法法则:总复杂度等于量级最大的那段代码的复杂度
- 乘法法则:嵌套代码的复杂度等于嵌套内外代码复杂度的乘积
最好、最坏时间复杂度
1 | int find(int[] array, int n, int x) |
代码中时间度复杂度会因为x在不在数组中变化,如果x在数组中则O(n)=1,否则O(n)=n。
平均时间复杂度
要查找的变量x在数组中的位置,有n+1种情况:在数组的0~n-1位置中和不在数组中。我们把每种情况下,查找需要遍历的元素个数累加起来,然后再除以n+1,就可以得到需要遍历的元素个数的平均值:
$$
\frac{1+2+3+\cdots+n+n}{n+1}=\frac{n(n+3)}{2(n+1)}
$$
考虑到在数组里和不在数组里的概率,以及出现在每个位置的概率,实际上应该是
$$
\begin{aligned} & 1 \times \frac{1}{2 n}+2 \times \frac{1}{2 n}+3 \times \frac{1}{2 n}+\dots+n \times \frac{1}{2 n}+n \times \frac{1}{2}\ = &\frac{3 n+1}{4} \end{aligned}
$$
用大O表示法来表示,去掉系数和常量,这段代码的加权平均时间复杂度仍然是O(n)。
均摊时间复杂度
1 | // array表示一个长度为n的数组 |
$$
1 \times \frac{1}{n+1}+1 \times \frac{1}{n+1}+\dots+1 \times \frac{1}{n+1}+n \times \frac{1}{n+1}=O(1)
$$
每一次O(n)的插入操作,都会跟着n-1次O(1)的插入操作,所以把耗时多的那次操作均摊到接下来的n-1次耗时少的操作上,均摊下来,这一组连续的操作的均摊时间复杂度就是O(1)。
思考
1 | // 全局变量,大小为10的数组array,长度len,下标i。 |
时间复杂度:
最好:O(1)
最坏:O(n)
均摊:O(1) 因为前N个操作都是O(1),最后一个均摊到前n个
空间复杂度:
最好:O(1)
最坏:O(n)