LeetCode 21. 合并两个有序链表 链表合并 Java实现

21. 合并两个有序链表

题目来源

21. 合并两个有序链表

题目分析

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

题目难度

  • 难度:简单

题目标签

  • 标签:链表

题目限制

  • 两个链表的节点数目范围是 [0, 50]
  • -100 <= Node.val <= 100

解题思路

思路:

  1. 问题定义

    • 本题要求将两个已经排好序的链表合并成一个新的有序链表。
  2. 核心算法

    • 迭代法:通过创建一个哨兵节点 head 和一个当前指针 cur,逐一比较两个链表的节点值,将较小的节点接到 cur 后面,最后将剩余的节点拼接到新链表的末尾。
    • 合并两个链表中较小的节点,并将其余的部分递归合并。
  3. 关键步骤

    • 迭代过程中,始终保持链表的有序性。
    • 过程的每一步都处理当前最小的节点,并将剩余的部分继续合并。

核心算法步骤

迭代法
  1. 创建哨兵节点:初始化一个哨兵节点 head,并用指针 cur 指向它。
  2. 遍历比较:遍历两个链表,比较 list1list2 当前节点的值,将较小值的节点接到 cur 后面,并移动相应链表的指针。
  3. 拼接剩余部分:当其中一个链表遍历完后,直接将另一个链表剩余部分接到新链表的末尾。

代码实现

以下是迭代法的 Java 代码实现:

/**
 * 21. 合并两个有序链表
 * @param list1 链表1
 * @param list2 链表2
 * @return 合并后的链表
 * @apiNote 迭代法,时间复杂度O(n),空间复杂度O(1)
 */
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
    ListNode head = new ListNode();
    ListNode cur = head;
    
    while (list1 != null && list2 != null) {
        if (list1.val < list2.val) {
            cur.next = list1;
            list1 = list1.next;
        } else {
            cur.next = list2;
            list2 = list2.next;
        }
        cur = cur.next;
    }
    cur.next = list1 != null ? list1 : list2;
    return head.next;
}

代码解读

  • 哨兵节点:哨兵节点 head 只是为了简化链表操作,最后返回 head.next 作为新链表的头节点。
  • 当前指针cur 用来拼接较小值的节点并移动指针,以保证链表的有序性。
  • 剩余部分:当其中一个链表遍历结束后,直接将另一个链表的剩余部分拼接到新链表的末尾。

性能分析

  • 时间复杂度O(n)n 为两个链表的节点数之和,每个节点只被遍历一次。
  • 空间复杂度O(1),仅使用了常数级的辅助空间,没有额外分配新节点。

复杂度结果

复杂度

测试用例

你可以使用以下测试用例来验证代码的正确性:

// 测试用例1
ListNode list1 = new ListNode(1, new ListNode(2, new ListNode(4)));
ListNode list2 = new ListNode(1, new ListNode(3, new ListNode(4)));
ListNode mergedList1 = mergeTwoLists(list1, list2);
printList(mergedList1); // 输出: 1 -> 1 -> 2 -> 3 -> 4 -> 4

// 测试用例2
ListNode list3 = null;
ListNode list4 = new ListNode(0);
ListNode mergedList2 = mergeTwoLists(list3, list4);
printList(mergedList2); // 输出: 0

扩展讨论

优化写法

  • 递归法:可以通过递归的方式实现合并两个有序链表,代码更为简洁,但空间复杂度为 O(n)
public ListNode mergeTwoListsRecursive(ListNode list1, ListNode list2) {
    if (list1 == null) return list2;
    if (list2 == null) return list1;
    if (list1.val < list2.val) {
        list1.next = mergeTwoListsRecursive(list1.next, list2);
        return list1;
    } else {
        list2.next = mergeTwoListsRecursive(list1, list2.next);
        return list2;
    }
}

其他实现

  • 双指针法:在不使用哨兵节点的情况下,可以直接操作 list1list2,但需要处理初始条件和特殊情况,代码会稍显复杂。

总结

这道题目考察了链表的基本操作,通过迭代和递归两种方法都能有效地合并两个有序链表。迭代法更适合处理链表较长的情况,而递归法则在代码上更加简洁。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值