给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。

示例 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

解题思路

暴力法遍历

创建K个指针指向K个ListNode,通过遍历不断获取最小的那个,将其放到结果中。但是消耗比较大,循环比较多。

分治法

将K个ListNode不断二分,直到分出的组内只有一个或者两个ListNode,就可以使用之前做过的合并两个链表来完成。

代码实现:

var mergeKLists = function(lists) {
if (lists.length === 0) return null;
return merge(lists, 0, lists.length - 1);
};

function merge(lists, left, right) { //将链表进行二分,进行两个链表的合并操作
if (left === right) return lists[left]; //如果left === right 说明是同一个链表,已经合并完成
const mid = Math.floor((left + right) / 2); //获取中间位置
const l1 = merge(lists, left, mid); //递归获取左边的链表的合并后的结果
const l2 = merge(lists, mid + 1, right); //递归获取右边链表合并后的结果
return mergeTwoLists(l1, l2); //最后把左右两边的链表合并
}


//合并两个链表
function mergeTwoLists(l1, l2) {
const dummy = new ListNode();
let curr = dummy; //创建一个指针
while (l1 && l2) { //当l1和l2都有值的时候比较两者大小,哪个小就把指针的next指向哪个
if (l1.val < l2.val) {
curr.next = l1;
l1 = l1.next;
} else {
curr.next = l2;
l2 = l2.next;
}
curr = curr.next; //比较完之后,把指针向后推一位
}
curr.next = l1 || l2; //如果其中一个不存在,即剩下的节点都是长度较长的那个
return dummy.next;
}