题目链接:合并两个单链表
目录
思路一:递归
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{
if(list1==NULL)
{
return list2;
}
if(list2==NULL)
{
return list1;
}
if(list1->val<=list2->val)
{
list1->next=mergeTwoLists(list1->next,list2);
return list1;
}
list2->next=mergeTwoLists(list1,list2->next);
return list2;
}
递归不要想的太深,这时新手常会犯的错误。
这里就画了前两层的图,如果list1继续往下走的话,返回的时候,需要将自身的地址返回到上一级才能让上一级和list1链接,list2也是。
引用一份大佬的解释:
关于return list1的个人理解: 递归的核心在于,我只关注我这一层要干什么,返回什么,至于我的下一层(规模减1),我不管,我就是甩手掌柜.
好,现在我要merge list1,list2.我要怎么做?
- 显然,如果list1空或list2空,我直接返回L1或L2就行,这很好理解.
- 如果list1第一个元素小于list2的? 那我得把list1的这个元素放到最前面,至于后面的那串长啥样 ,我不管. 我只要接过下级员工干完活后给我的包裹, 然后把我干的活附上去(令list1->next = 这个包裹)就行
- 这个包裹是下级员工干的活,即merge(list1->next, list2)
我该返回啥?
- 现在不管我的下一层干了什么,又返回了什么给我, 我只要知道,假设我的工具人们都完成了任务, 那我的任务也就完成了,可以返回最终结果了
- 最终结果就是我一开始接手的list1头结点+下级员工给我的大包裹,要一并交上去, 这样我s的boss才能根据我给它的list1头节点往下找,检查我完成的工作
思路二:尾插
这个思路相对来说较好一点,易理解,易上手。
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{
struct ListNode* head =
(struct ListNode*)malloc(sizeof(struct ListNode));
struct ListNode* tail = head;
tail->next=NULL;
while(list1&&list2)
{
if(list1->val<list2->val)
{
tail->next=list1;
list1=list1->next;
tail = tail->next;
}
else
{
tail->next=list2;
list2=list2->next;
tail = tail->next;
}
}
if(list1)
{
tail->next = list1;
}
if(list2)
{
tail->next = list2;
}
struct ListNode* val = head->next;
return val;
}