「这是我参与12月更文挑战的第13天,活动详情查看:2021最后一次更文挑战」
合并K个升序链表
给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。
示例 1:
输入:lists = [[1,4,5],[1,3,4],[2,6]]
输出:[1,1,2,3,4,4,5,6]
解释:链表数组如下:
[
1->4->5,
1->3->4,
2->6
]
将它们合并到一个有序链表中得到。
1->1->2->3->4->4->5->6
示例 2:
输入: lists = []
输出: []
示例 3:
输入: lists = [[]]
输出: []
提示:
- k == lists.length
- 0 <= k <= 10^4
- 0 <= lists[i].length <= 500
- -10^4 <= lists[i][j] <= 10^4
- lists[i] 按 升序 排列
- lists[i].length 的总和不超过 10^4
递归分治 合并
思路
- 需要一个两个合并链表的函数mergeTwoList
- 将数组中的链表两两合并
- 处理边界值,lists没有值的时候返回null
mergeTwoList合并链表函数通过不断比较两链表的首节点大小,来找出当前最小节点,将最小节点拼接在新节点末尾,当一个链表完全拼接完毕后,剩余链表直接拼接在新链表后方,返回新链表的next
merge函数用来合并lists的第l位到第r位的链表,只要l!==r就会进行二分,继续递归调用merge,然后在最后用mergeTwoList来合并两个结果得到合并后的链表
var mergeTwoList = function (a, b) {
if (!a || !b) {
return a ? a : b
}
var node1 = a
var node2 = b
var newHead = new ListNode('head')
var last = newHead
while (node1 && node2) {
if (node1.val < node2.val) {
last = last.next = node1
node1 = node1.next
} else {
last = last.next = node2
node2 = node2.next
}
}
last.next = node1 ? node1 : node2
return newHead.next
}
var merge = function(lists,l,r){
if(l===r) return lists[l]
if(l>r) return null
var mid = (l+r)>>1
return mergeTwoList(merge(lists,l,mid),merge(lists,mid+1,r))
}
var mergeKLists = function (lists) {
return merge(lists,0,lists.length-1)
};
队列分治 合并
思路
上面通过递归来合并,这里我们也可以通过队列来合并
- 把lists本身当做一个队列
- 处理边界,len为0的时候直接返回null
- 如果len>1,证明至少两个链表,分别从lists头部取出前两个节点进行合并,将合并结果push到lists尾部
- 最后lists中只会剩下一个链表 返回lists[0]
var mergeTwoList = function (a, b) {
...
}
var mergeKLists = function (lists) {
if (lists.length === 0) return null
while (lists.length > 1) {
var node1 = lists.shift()
var node2 = lists.shift()
lists.push(mergeTwoList(node1, node2))
}
return lists[0]
};