🕒 题目:
🔎 21. 合并两个有序链表【难度:简单🟢】
🔎 面试题 25:合并两个排序的链表【剑指offer】
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
- 示例 1:

输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]
- 示例 2:
输入:l1 = [ ], l2 = [ ]
输出:[ ]
- 示例 3:
输入:l1 = [ ], l2 = [0]
输出:[0]
提示:
- 两个链表的节点数目范围是
[0, 50] -100 <= Node.val <= 100l1和l2均按 非递减顺序 排列
⌛ 总体思路:
两个链表的结点一一比较,一开始取较小的结点作为新链表的头,然后取较小的结点尾插到新链表上
🕘 方法①-无哨兵结点的遍历
💡 思路:合并两个链表和合并两个数组的最简单思路都一样的,都是从两个表中比较元素,取小的尾插;

⚡ 注意:第一次插入的时候,头插要单独处理,因为tail == NULL,无法使用tail->next;
其次,l1和l2比较到尾时候,谁先结束到尾,还没到尾的,直接把剩下的链表插入到newhead链表中,即tail->next;
struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2)
{
//假如哪个链表为NULL,就返回另一个链表的头结点即可!
if(l1 == NULL)
return l2;
if(l2 == NULL)
return l1;
struct ListNode* newhead = NULL;
struct ListNode* tail = NULL;
while(l1 && l2)
{
if(l1->val < l2->val) //l1比较小
{
//第一次尾插的是头结点的话,那么要单独处理
if(newhead == NULL)
{
newhead = tail = l1;
}
else
{
tail->next = l1; //尾插不是头结点
tail = tail->next;
}
//迭代l1继续往前走
l1 = l1->next;
}
else //l2比较小或者相等
{
//第一次尾插的是头结点的话,那么要单独处理
if(newhead == NULL)
{
newhead = tail = l2;
}
else{
tail->next = l2; //尾插不是头结点
tail = tail->next;
}
//迭代l2继续往前走
l2 = l2->next;
}
}
//退出循环后,单独判断谁先结束,还没结束的链表直接赋值到tail->next;
if(l1)
{
tail->next = l1;
}
if(l2)
{
tail->next = l2;
}
return newhead;
}

🕘 方法②-有哨兵结点的遍历
💡 思路:有哨兵位就很好处理了,处理尾插的逻辑就和头插一模一样,不用担心第一次插入的值是否为头部;
⚡ 注意:返回时候要返回哨兵结点的next;
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{
struct ListNode* guard = (struct ListNode*)malloc(sizeof(struct ListNode));
guard->next = NULL; //避免野指针
struct ListNode* tail = guard;
struct ListNode* cur1 = list1,*cur2 = list2;
while(cur1 &&cur2)
{
if(cur1->val < cur2->val)
{
tail->next = cur1;
cur1 = cur1->next;
}
else
{
tail->next = cur2;
cur2 = cur2->next;
}
tail = tail->next;
}
//退出循环后,单独判断谁先结束,还没结束的链表直接赋值到tail->next;
if(cur1)
tail->next = cur1;
if(cur2)
tail->next = cur2;
struct ListNode* head = guard->next;
free(guard);
return head;
}

🕘 方法③-递归
💡 思路:
- 比较两个链表
l1->val和l2->val:谁小就递归谁的next; - 假如
l1->val < l2->val:,那么递归合并l1->next 和 l2,返回l1即可; - 否则递归
l2->next和l1,返回l2即可!
struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2)
{
//递归条件
if(l1 == NULL)
return l2;
if(l2 == NULL)
return l1;
if(l1->val < l2->val)
{
l1->next = mergeTwoLists(l1->next,l2);
return l1;
}
else
{
l2->next = mergeTwoLists(l1,l2->next);
return l2;
}
}

这篇博客详细介绍了三种合并两个有序链表的方法:无哨兵结点的遍历、有哨兵结点的遍历以及递归。每种方法都提供了清晰的思路和代码实现,旨在确保合并后的链表仍然保持有序。在无哨兵方法中,需要注意首次插入和处理未完全遍历的链表。有哨兵方法则简化了尾插操作,而递归方法通过比较链表节点值的大小进行递归合并。这些方法对于理解和处理链表操作具有实用价值。
2408

被折叠的 条评论
为什么被折叠?



