合并两个排序的链表

170 阅读2分钟

题目

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

示例1:

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

0 <= 链表长度 <= 1000

来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/he… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

插入排序

构造哨兵节点 sentinel,sentinel.next = head1。遍历链表 head2 在链表 dummy 中寻找合适的插入位置。特别注意遍历完整个链表 dummy,发生空指针的情况, 返回 dummy.next。

双指针

题目描述两个链表时递增排序,你可以使用双指针 p q 遍历两个链表判定新链表的下一元素。算法流程如下:

  1. 初始化哨兵节点 dummy,dummy.next = head1;节点 curr 指向 dummy。

  2. 循环合并。当 p q 任意一个为空跳出循环,判定 p q 的 value 大小决定后继节点。

    1. 当 p.val < q.val 时,p 是下一后继节点, curr.next = p;
    2. 当 q.val ≥ q.val 时,q 是下一后继节点,curr.next = q;

    curr 前进一位,curr = curr.next; 循环往复执行。

  3. 合并剩余尾部链表。当 p 或 q 任意一个为空时,跳出第2步循环合并。

    判定 p == null 是否成立,将剩余尾部合并到 curr 节点。

代码实现

插入排序

public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        if (l1 == null || l2 == null) return l1 != null ? l1 : l2;
        ListNode dummy = new ListNode(0); dummy.next = l1;
        ListNode p = l2; ListNode lastSorted = dummy;
        while (p != null) {
            ListNode pred = lastSorted;
            while (pred.next != null && pred.next.val <= p.val) {
                pred = pred.next;
            }
            ListNode t = p.next;
            p.next = pred.next;
            pred.next = p;
            lastSorted = p;
            p = t;
        }
        return dummy.next;
    }

需要遍历两个链表时间复杂度是O(M+N) 其中M和N是链表的长度。采用原地排序算法空间复杂度是O(1)。

双指针

public ListNode twoPointer(ListNode l1, ListNode l2) {
        ListNode dummy = new ListNode(); dummy.next = l1;
        ListNode p = l1, q = l2, curr = dummy;
        while (p != null && q != null) {
            if (p.val < q.val) {
                curr.next = p;
                p = p.next;
            } else {
                curr.next = q; 
                q = q.next;
            }
            curr = curr.next;
        }
        curr.next = (p != null ? p : q);
        return dummy.next;
    }

需要遍历两个链表时间复杂度是O(M+N) 其中M和N是链表的长度。声明了 dummy, p, q, curr 变量,采用原地算法空间复杂度是O(1)。

知识点

链表的插入节点操作。

双指针和插入排序思想