[路飞]-leetcode 23合并K个有序链表

我参与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到堆中,只能下一个节点不存在停止循环

Guess you like

Origin juejin.im/post/7032298670733131812