21. 合并两个有序链表【难度:简单】
面试题 25:合并两个排序的链表【剑指offer】
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]
输入:l1 = [ ], l2 = [ ]
输出:[ ]
输入:l1 = [ ], l2 = [0]
输出:[0]
提示:
[0, 50]
-100 <= Node.val <= 100
l1
和 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;
}
}