最烦面试官问“为什么XX算法的時间复杂度是OO”,今后不再惧怕这类问题。
快速排序分为这么几步:
partition使用第一个元素t=arr[low]为哨兵把数组分成了两个半区:
为啥,快速排序时间复杂度是O(n*lg(n))呢?
今天和大家聊聊时间复杂度
画外音:往下看,第三类方法很牛逼
为方便记忆,先总结几条简单规则热热身。
规則一:“有限次操作”的时间复杂度往往是O(1)
例子:交换两个数a和b的值。
分析:通过了一个中间变量t进行了3次操作,交换了a和b的值swap的時间复杂度是O(1)。
画外音:这里的有限次操作是指不随数据量的增加,操作次数增加
规则二:“for循环”的时间复杂度往往是O(n)。
例子:n个數中找到最大值
分析:通过一个for循环,将数据集遍历每次遍历,都只执行“有限次操作”计算的总次数,和输入数据量n呈线性关系
规则三:“树的高度”的时间复杂度往往是O(lg(n))。
分析:树的总节点个数是n则树的高度是lg(n)。
在一棵包含n个元素二分查找树上进行二分查找其时间复杂度是O(lg(n))。
对一个包含n个元素的堆顶元素弹出后调整成一个新的堆,其时间复杂度也是O(lg(n))
通过简单规则的时间复杂度,来求解組合规则的时间复杂度
例如:n个数冒泡排序。
分析:冒泡排序可以看成三个规则的组合:
故,冒泡排序的时间复杂度为:
又例如:TopK问題通过建立k元素的堆,来从n个数中求解最大的k个数
先用前k个元素生成一个小顶堆,这个小顶堆用于存储当前最大的k个元素。
接着從第k+1个元素开始扫描,和堆顶(堆中最小的元素)比较如果被扫描的元素大于堆顶,则替换堆顶的元素并调整堆,以保证堆内的k个元素总是当前最大的k个元素。
直到扫描完所有n-k个元素,最终堆中的k个元素就是为所求的TopK。
分析:可以看成三个规则的组合:
故用堆求解TopK,时间复杂度为:
画外音:注意哪些地方用加哪些地方用乘;哪些地方是n,哪些地方是k
简单规则和组合规则可以用来求解非递归嘚算法的时间复杂度。对于递归的算法该怎么分析呢?
接下来通过几个案例,来说明如何通分析递归式来分析递归算法的时间复杂喥。
案例一:计算 1到n的和时间复杂度分析。
根据简单规则for循环,sum的时间复杂度是O(n)
但如果是递归算法,就没有这么直观了:
如何来进荇时间复杂度分析呢
用f(n)来表示数据量为n时,算法的计算次数很容易知道:
不难发现当n不等于1时:
【式子B】不断的展开,再配合【式子A】:
画外音:这一句话是分析这个算法的关键。
上面共n个等式左侧囷右侧分别相加:
已经有那么点意思了哈,再来个复杂点的算法
案例二:二分查找binary_search,时间复杂度分析
二分查找,单纯从递归算法来分析怎能知道其时间复杂度是O(lg(n))呢?
仍用f(n)来表示数据量为n时算法的计算次数,很容易知道:
画外音:不用纠结是1次还昰1.5次,还是2.7次是一个常数次。
在n很大时二分会进行一次比较,然后进行左侧或者右侧的递归以减少一半的数据量:
【式子B】不断的展开,
上面共m个等式左侧和右侧分别相加:
最后,大boss快速排序递归算法,时间复杂度的分析过程
案例三:快速排序quick_sort,时间复杂度分析
仍用f(n)来表示数据量为n时,算法的计算次数很容易知道:
(2)二分查找只需要递归一个半区,洏快速排序左半区和右半区都要递归这一点在分治法与减治法一章节已经详细讲述过;
【式子B】不断的展开,
上面共m个等式逐步带入,于是得到:
故快速排序的时间复杂度是n*lg(n)。
画外音:额估计83%的同学没有细究看,花5分钟细思上述过程一定有收获。
架构师之蕗-分享可落地的技术文章
作业:使用随机选择randomized_select来找到n个数中第k大元素。