Merge k Sorted Lists
- leetcode: Merge k Sorted Lists | LeetCode OJ
这种方法非常简单直接,但是时间复杂度较高,容易出现 TLE.
源码分析
- 由于头节点不定,我们使用
dummy
节点。 - 使用
last
表示每次归并后的新链表末尾节点。 count
用于累计链表表头节点为NULL
的个数,若与 vector 大小相同则代表所有节点均已遍历完。tempVal
用于保存每次比较 vector 中各链表表头节点中的最小值,index
保存本轮选择归并过程中最小值对应的链表索引,用于循环结束前递推该链表表头节点。
复杂度分析
由于每次for
循环只能选择出一个最小值,总的时间复杂度最坏情况下为 O(k \cdot \sum ^{k}_{i=1}l_i). 空间复杂度近似为 O(1).
源码分析
实现合并两个链表的子方法后就没啥难度了,mergeKLists
中左半部分链表初始化为lists[0]
, for
循环后迭代归并head
和lists[i]
.
复杂度分析
合并两个链表时最差时间复杂度为 O(l1+l_2), 那么在以上的实现中总的时间复杂度可近似认为是 l_1 + l_1+l_2 +…+l_1+l_2+…+l_k = O(\sum {i=1} ^{k} (k-i) \cdot l_i). 比起题解1复杂度是要小一点,但量级上仍然差不太多。实际运行时间也证明了这一点,题解2的运行时间差不多时题解1的一半。那么还有没有进一步降低时间复杂度的可能呢?当然是有的,且看下题分解…
源码分析
由于需要建立二分递归模型,另建一私有方法helper
引入起止位置较为方便。下面着重分析helper
。
- 分两种边界条件处理,分别是和
start + 1 == end
. 虽然第二种边界条件可以略去,但是加上会节省递归调用的栈空间。 - 使用分治思想理解
helper
,left
和right
的边界处理建议先分析几个简单例子,做到不重不漏。 - 注意
merge2Lists
中传入的参数,为lists[start]
而不是start
…
在mergeKLists
中调用helper
时传入的end
参数为lists.size() - 1
,而不是lists.size()
.
复杂度分析
优化后的运行时间显著减少!由题解2中的500+ms 减至40ms 以内。