LeetCode - 21. 合并两个有序链表

发布于:2025-06-06 ⋅ 阅读:(20) ⋅ 点赞:(0)

目录

题目

合并两个有序链表的思路

读者可能的错误写法

正确的写法


题目

21. 合并两个有序链表 - 力扣(LeetCode)

合并两个有序链表的思路

处理边界情况:

  • 如果list1为空,直接返回list2
  • 如果list2为空,直接返回list1

使用哨兵节点:

  • 创建一个哨兵节点dummy(值为0)作为合并链表的起点
  • 使用一个current指针跟踪当前合并位置

合并过程:

  • 同时遍历两个链表,比较当前节点的值
  • 将较小值的节点连接到current的next
  • 移动较小值所在的链表指针和current指针
  • 重复这个过程直到其中一个链表遍历完毕

处理剩余节点:

  • 当其中一个链表遍历完成后,将另一个链表的剩余部分直接连接到current的next
  • 这是有效的,因为剩余部分已经是有序的

返回结果:

  • 返回dummy->next作为合并后的链表头
  • 释放dummy节点以避免内存泄漏

时间和空间复杂度

  • 时间复杂度:O(m+n),其中m和n分别是两个链表的长度
  • 空间复杂度:O(1),只使用了常数额外空间

读者可能的错误写法

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
        ListNode* dummy = new ListNode(0);
        ListNode* newhead = dummy;
        while(list1 && list2)
        {
            if(list1->val <= list2->val)
            {
                newhead = list1;
                list1 = list1->next;
            }
            else
            {
                newhead = list2;
                list2 = list2->next; 
            }
            newhead = newhead->next;
        }

        while(list1)
        {
                newhead = list1;
                list1 = list1->next;
                newhead = newhead->next;
        }
        while(list2)
        {
                newhead = list2;
                list2 = list2->next; 
                newhead = newhead->next;
        }

        return newhead;
    }
};

上面代码有一些错误

空指针检查:

  • 没有检查list1或list2是否为nullptr,直接访问list1->val和list2->val会导致空指针错误

哨兵节点使用错误:

  • 创建了dummy节点但没有正确使用
  • newhead = dummy->next是错误的,因为dummy->next初始为nullptr
  • 没有通过dummy构建链表

节点连接逻辑错误:

  • 没有正确连接节点,只是将newhead指向不同节点
  • newhead = newhead->next会导致丢失之前的节点

返回值错误:

  • 最终返回newhead,但这可能是nullptr或指向链表末尾

正确的写法

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
        if(!list1)
        {
            return list2;
        }
        if(!list2)
        {
            return list1;
        }
        ListNode* dummy = new ListNode(0);
        ListNode* cur = dummy;
        while(list1 && list2)
        {
            if(list1->val <= list2->val)
            {
                cur->next = list1;
                list1 = list1->next;
            }
            else
            {
                cur->next = list2;
                list2 = list2->next; 
            }
            cur = cur->next;
        }

        //while(list1) //这种写法也对,但是太麻烦了
        //{
                //cur->next = list1;
                //list1 = list1->next;
                //cur = cur->next;
        //}
        //while(list2)
        //{
                //cur->next = list2;
                //list2 = list2->next; 
                //cur = cur->next;
        //}

        if (list1)
        {
            current->next = list1;
        } 
        if (list2)
        {
            current->next = list2;
        } 
        

        ListNode* newHead = dummy->next;
        delete dummy;
        return newHead;
    }
};