剑指 Offer(18)——合并两个排序的链表

194 阅读2分钟

这是我参与8月更文挑战的第18天,活动详情查看:8月更文挑战

题目 输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的。 示例1:

输入:1->2->4, 1->3->4 输出:1->1->2->3->4->4

思路 生成一个新链表 保存头部h 循环比较l1 l2的值head.next指向较小的 比较完毕 head.next指向还有剩余的链表 返回h.next 合并两个排序的链表,如图:

已排序链表1和已排序链表2合并后的已排序链表3

过程:

(a)链表1的头结点的值小于链表2的头结点的值,因此链表1的头结点是合并后链表的头结点。 (b)在剩余的结点中,链表2的头结点的值小于链表1的头结点的值,因此链表2的头结点是剩余 结点的头结点,把这个结点和之前已经合并好的链表的尾结点链接起来。 首先将list中的每个链表比较首元素,然后依次加入优先队列(或者一个堆,我这里使用堆)

q : 1 1 2 | | | 4 3 6 | | 5 4 1 2 3 4 5 然后判断这个优先队列是否为空,不为空,我们弹出队首元素(1),接着判断这个弹出的元素作为一个链表节点,其后是否还有元素,如果有元素,将元素加入队列。同时将结果加入到result中

q : 1 2 4 | | | 3 6 5 | 4

result: 1 首先可以确定的是,链表1和链表2本身就是递增的,所以合并的过程可以从链表1,2的头结点开始,先比较1,2的头结点中值的大小,将小的值的结点(比如为链表1头结点)作为合并后的链表(链表3)的头结点。随后可以考虑成链表1的从原链表第二个结点开始,再次重复上面的步骤,这样就变成了一个递归问题。

代码

var mergeTwoLists = function (l1, l2) {
    var head = new ListNode()
    var h = head
    while (l1 && l2) {
        if (l1.val < l2.val) {
            head.next = l1;
            l1 = l1.next
        } else {
            head.next = l2;
            l2 = l2.next
        }
        head = head.next
    }
    if (l1) head.next = l1
    if (l2) head.next = l2
    return h.next
};