我参与11月更文挑战的第17天,活动详情查看:2021最后一次更文挑战
给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。
1. 思路一:
- 将k个链表的节点添加到数组里
- 对数组进行排序
- 最后将排好序的数组节点串起来
const nodes = []
for(let list of lists){
while(list){
nodes.push(list)
list = list.next
}
}
nodes.sort((a,b) => a.val - b.val)
const head = new ListNode(0)
let cur = head
for(let node of nodes){
cur = cur.next = node;
}
return head.next
复制代码
2. 思路二 逐一比较
1 -> 3 1 -> 2 -> 3 ... 将每个链表的头节点最小的那个依次拿出来,最后串起来
2 -> 5
4 -> 6
var mergeKList = function (lists) {
// 边界
if(lists == null || lists.length == 0)return null
// 声明一个虚拟头节点用来拼接
const head = new ListNode(0)
let cur = head // 当前指针
while(true){
let minIndex = -1 // 标记头节点的最小索引
// 遍历去最小节点
for(let i=0; i< lists.length; i++){
if(lists[i] == null) continue
if(minIndex == -1 || lists[i].val < lists[minIndex].val){
minIndex = i
}
}
// minIndex 没有了 跳出循环
if(minIndex == -1){
break
}
// 拼接
cur = cur.next = lists[minIndex]
lists[minIndex] = lists[minIndex].next // 拼接完毕后最小头节点移动到下一位
}
return head.next
}
复制代码
3.思路三 逐一两两合并 list[0]和list[1] 合并到list[0] 在和lists[2] 比较 依次类推
这个思路是从合并两个有序链表而来。 不过这样的缺点比较明显, list[0]规模每次合并的时候规模越来越大。合并之后还要继续比较。
let head = new ListNode(0)
let mid = -1
for(let i = 1; i< lists.length; i++){
mid = (i+ lists.length ) >> 1
lists[0] = mergeTwoLists(lists[0], list[mid])
}
return lists[0]
function mergeTwoLists(k1, k2){
if(k1 == null)return k2
if(k2 == null)return k1
head.next = null // 每次开始时置空虚头节点
let cur = head
while(k1 !=null && k2 !=null){
// 递归比较取最小节点 指针向后移
if(k1.val< k2.val}{
cur = cur.next = k1
k1 = k1.next
}else{
cur = cur.next = k2
k2 = k2.next
}
}
// 循环结束 ,拼接未比较完的链表
if(k1 ==null){
cur.next = k2
}else{
cur.next = k1
}
return head.next
}
复制代码
思路四 最小堆 可以看看最小堆的实现
建立最小堆, 将k个链表的头节点push到堆中,然后取出堆顶元素依次拼接链表,堆顶元素的下一个节点push到堆中,只能下一个节点不存在停止循环