原题链接:将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
最简思路:归并(建立新链表,比较两个原链表中的val,谁小拿谁)
定义两个指针,分别存放新链表的头结点和前一个结点(即存储此刻已链接的新节点的前一个结点)
处理两种特殊情况:
其一:原链表为空的情况,list1 为空,则返回 list2,反之,返回 list1。这里不用担心两者均为空的情况,因为如果两者均为空,会直接进入第一个if语句,返回 list2,list2也是为空,所以无需做额外的处理。
其二:因为采用归并思路,所以遍历完原链表后,会有至少一个结点没有链接到新结点上。所以需要判断原链表中哪个为空,然后通过前一个结点 tail 链接到那个不为空的原链表上。新链表就全部链接完毕。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
//接口实现
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
struct ListNode* head = NULL;
struct ListNode* tail = NULL;
if(list1 == NULL)
return list2;
if(list2 == NULL)
return list1;
while(list1 && list2)
{
if(list1->val <= list2->val)
{
if(tail == NULL)
{
tail = head = list1;
}
else
{
tail->next = list1;
tail = list1;
}
list1 = list1->next;
}
else
{
if(tail == NULL)
{
tail = head = list2;
}
else
{
tail->next = list2;
tail = list2;
}
list2 = list2->next;
}
}
if(list1)
{
tail->next = list1;
}
if(list2)
{
tail->next = list2;
}
return head;
}
第二种思路比较绕,不建议,可以当作私下锻炼逻辑去写一写。
这种思路则没有建立新链表,而是记录最小的结点的地址,将其作为头节点返回。
此思路很容易被忽略的点就是:如果 list1的val 比 list2 小,不能将 list2 直接尾插到 list1 的后面,因为 list1 后面的结点并不一定大于 list2,所以需要确保 list1 后面的结点全部小于 list2,或是到某一个结点小于 list2 时,才能将 list2 尾插其后。
反之同理。list1 的 val 比 list2 大,也需要判断其后面的结点是否也比 list2 大,才可将 list1 尾插到 list2 后面。
需要处理的特殊情况除了传参可能为空以外,走到最后一个结点时,直接将其指向的 next 链接到 另一个链表上之后(next 链接到新链表后,所指向的 next 肯定不为空了),要将其指针置空,避免死循环。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
//接口实现
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
struct ListNode* list = NULL;
struct ListNode* next = NULL;
if (list1 == NULL)
return list2;
if (list2 == NULL)
return list1;
while (list1 && list2)
{
if (list1->val <= list2->val)
{
if (list == NULL)
{
list = list1;
}
//如果此链表指向的next为空,则直接在另一个链表的尾部链接上此链表
if (list1->next)
{
if (list1->next->val <= list2->val)
{
list1 = list1->next;
}
else
{
next = list1->next;
list1 -> next = list2;
list1 = next;
}
}
else
{
list1->next = list2;
//此链表必须置空。因为 list1的next 已经链接到 list2上去了,list1的next肯定不
为空,如果不置空,就死循环了
list1 = NULL;
}
}
else
{
if (list == NULL)
{
list = list2;
}
//同理
if (list2->next)
{
if (list1->val <= list2->next->val)
{
next = list2->next;
list2->next = list1;
list2 = next;
}
else
{
list2 = list2->next;
}
}
else
{
list2->next = list1;
//同理
list2 = NULL;
}
}
}
return list;
}