合并两个有序链表

  1. 1. 题目描述
  2. 2. 解决思路
  3. 3. 关键代码
  4. 4. 复杂度分析

1. 题目描述

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

示例 1:

img

输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]

示例 2:

输入:l1 = [], l2 = []
输出:[]

示例 3:

输入:l1 = [], l2 = [0]
输出:[0]

2. 解决思路

可以使用迭代方法来实现有序链表的合并.

假设有两个有序链表 list1和list2, 当这两个链表都不是空链表时,选择头节点中较小的一个作为合并链表的头节点,.

移动有序链表的指针,比较list1和list2最新的头节点, 添加到合并链表中.

3. 关键代码

/**
 * 合并两个有序列表
 *
 * @param list1 有序链表1, 顺序: 由小到大
 * @param list2 有序链表2, 顺序: 由小到大
 * @return ListNode 合并后的有序链表
 */
public static ListNode merge(ListNode list1, ListNode list2) {
    // 极值判断
    if (list1 == null || list2 == null) {
        return list1 == null ? list2 : list1;
    }

    ListNode cur1 = list1; // list1中当前正在比较的头节点
    ListNode cur2 = list2; // list2中当前正在比较的头节点
    ListNode head = null; // 已完成合并操作的链表(默认头节点是两个有序链表头节点中较小的一个)
    if (cur1.val <= cur2.val) {
        head = cur1;
        cur1 = cur1.next; // 更新cur1的头节点
    } else {
        head = cur2;
        cur2 = cur2.next; // 更新cur2的头节点
    }

    ListNode pre = head; // 临时节点,开始指向head, 后面通过pre不断调整head节点的next属性的引用

    while (cur1 != null && cur2 != null) { // 仅当两个队列当前操作的节点都不为空时,才需要进行比较与合并操作
        if (cur1.val <= cur2.val) {
            pre.next = cur1; // 当cur1的值小于cur2时,next指向cur1
            cur1 = cur1.next; // cur1节点后移,继续后面节点的比较
        } else {
            pre.next = cur2; // 当cur2的值小于cur1时,将cur2作为待合并的节点
            cur2 = cur2.next; // cur2节点后移,继续后面节点的比较
        }

        // 这一行同时也不断调整了head节点的next属性,扩充了head链表
        pre = pre.next; // 链表指针后移
    }

    // 当其中一个链表(假设是cur1)的最后一个节点完成了合并操作,而另一个链表(假设是cur2)还有剩余节点未合并,
    // 此时就需要将最后完成合并的节点(pre节点)的next指向还有节点未合并的链表(不为空的链表).
    // 这一步是必须存在的,因为两个有序链表合并,必然会存在其中一个节点先完成合并.
    pre.next = cur1 != null ? cur1 : cur2;

    // 返回合并后,完整的有序链表
    return head;
}

完整测试代码:

https://github.com/GeorgeChan95/algorithm/blob/master/src/main/java/com/george/mergeTwoList/MergeTwoList.java

4. 复杂度分析

  • 时间复杂度:O(n+m),其中 n 和 m 分别为两个链表的长度。因为每次循环迭代中,l1 和 l2 只有一个元素会被放进合并链表中, 因此 while 循环的次数不会超过两个链表的长度之和。所有其他操作的时间复杂度都是常数级别的,因此总的时间复杂度为 O(n+m)。

  • 空间复杂度:O(1)。我们只需要常数的空间存放若干变量。


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 george_95@126.com