题目描述:
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。


新建一个链表 newList 用于存放合并后的链表,设置一个指针指向该链表最后一个位置的 next,分别判断两个链表当前位置的大小,将值小的元素插入 newList 的末尾,并向后移动当前链表的位置,直到两个链表中有一个链表为空。然后再依次查看哪个链表不为空,将不为空的链表剩下的元素插入 newList 中。
其中需要考虑的问题是应该如何向 newList 中插入元素。首先创建一个 newList 指针并指向空,同时创建一个指向newList末尾结点的指针 last,令 last=newList。
例如实例1,l1和l2初始时都指向头结点,判断头结点的元素大小,得到 l2的元素,确定元素后将该元素赋值给一个 cur 指针,由于当前 newList 指向为空,所以此时要让 newList=cur,并让last=newList,同时,也要让 l2 链表的当前位置向后移动,也就是 l2 = l2->next。保证每次last指向的都是newList的最后一个元素。当newList不为空时,将确定的元素赋给cur指针后,将newList末尾的指针的下一个指向cur,即 last->next=cur,然后再更新last的位置。让 last = last->next. 依次遍历,最后返回 newList。
代码如下:
- /**
- * Definition for singly-linked list.
- * struct ListNode {
- * int val;
- * struct ListNode *next;
- * };
- */
- struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
- struct ListNode* newList=NULL;
- if(list1==NULL && list2==NULL)
- {
- return newList;
- }
- struct ListNode* last=newList;
- while(list1!=NULL && list2!=NULL)
- {
-
- if(list1->val < list2->val)
- {
- struct ListNode* cur = (struct ListNode*)malloc(sizeof(struct ListNode));
- cur->val = list1->val;
- cur->next = NULL;
- if(newList==NULL)
- {
- newList = cur;
- last = newList;
- }
- else
- {
- last->next = cur;
- last = last->next;
- }
- list1 = list1->next;
- }
- else
- {
- struct ListNode* cur = (struct ListNode*)malloc(sizeof(struct ListNode));
- cur->val = list2->val;
- cur->next = NULL;
- if(newList==NULL)
- {
- newList = cur;
- last = newList;
- }
- else
- {
- last->next = cur;
- last = last->next;
- }
- list2 = list2->next;
- }
- }
- while(list1!=NULL)
- {
- struct ListNode* cur = (struct ListNode*)malloc(sizeof(struct ListNode));
- cur->val = list1->val;
- cur->next = NULL;
- if(newList==NULL)
- {
- newList = cur;
- last = newList;
- }
- else
- {
- last->next = cur;
- last = last->next;
- }
- list1 = list1->next;
- }
- while(list2!=NULL)
- {
- struct ListNode* cur = (struct ListNode*)malloc(sizeof(struct ListNode));
- cur->val = list2->val;
- cur->next = NULL;
- if(newList==NULL)
- {
- newList = cur;
- last = newList;
- }
- else
- {
- last->next = cur;
- last = last->next;
- }
- list2 = list2->next;
- }
- return newList;
- }
对于 newList 为空的情况,每次循环都需要进行判断较为麻烦,所以在 创建 newList 的时候,首先创建一个值为-1 的节点,令 last指向 newList,然后直接按照上述newList不为0的情况判断即可。遍历完两个链表并将值都赋给 newList后,返回值返回newList->next,跳过第一个元素。
改进后代码:
- /**
- * Definition for singly-linked list.
- * struct ListNode {
- * int val;
- * struct ListNode *next;
- * };
- */
- struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
- struct ListNode* newList=(struct ListNode*)malloc(sizeof(struct ListNode));
- newList->val = -1;
- newList->next = NULL;
- if(list1==NULL && list2==NULL)
- {
- return newList->next;
- }
- struct ListNode* last=newList;
- while(list1!=NULL && list2!=NULL)
- {
-
- if(list1->val < list2->val)
- {
- struct ListNode* cur = (struct ListNode*)malloc(sizeof(struct ListNode));
- cur->val = list1->val;
- cur->next = NULL;
- last->next = cur;
- last = last->next;
- list1 = list1->next;
- }
- else
- {
- struct ListNode* cur = (struct ListNode*)malloc(sizeof(struct ListNode));
- cur->val = list2->val;
- cur->next = NULL;
- last->next = cur;
- last = last->next;
- list2 = list2->next;
- }
- }
- while(list1!=NULL)
- {
- struct ListNode* cur = (struct ListNode*)malloc(sizeof(struct ListNode));
- cur->val = list1->val;
- cur->next = NULL;
- last->next = cur;
- last = last->next;
- list1 = list1->next;
- }
- while(list2!=NULL)
- {
- struct ListNode* cur = (struct ListNode*)malloc(sizeof(struct ListNode));
- cur->val = list2->val;
- cur->next = NULL;
- last->next = cur;
- last = last->next;
- list2 = list2->next;
- }
- return newList->next;
- }
然而后来发现上面两种方法都不太好,每次都需要创建新的结点,继续改进代码:
- struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
- struct ListNode* newHead = NULL;
- newHead = (struct ListNode*)malloc(sizeof(struct ListNode));
- newHead->val = -1;
- newHead->next = NULL;
- struct ListNode* cur = newHead;
- while(list1 && list2)
- {
- if(list1->val < list2->val)
- {
- cur->next = list1;
- list1 = list1->next;
-
- }
- else
- {
- cur->next = list2;
- list2 = list2->next;
- }
- cur = cur->next;
- }
- if(list1)
- {
- cur->next = list1;
- }
- else if(list2)
- {
- cur->next = list2;
- }
- return newHead->next;
- }
使用递归不需要创建一个新的链表,直接在现有的两个链表中进行排序。 如下图,现在两个链表合并的函数是mergeTwoLists(L1, L2)


如上图,当前合并的链表应该为 L2->next = mergeTwoLists(L1, L2->next)

对于这次,应该为L1->next = mergeTwoLists(L1->next, L2)
递归的核心在于,只关注当前层要干什么,返回什么,至于我的下一层是不管的。
如果L1空,则返回L2,如果L2为空,则返回L1,这就是终止条件
如果L1第一个元素小于L2的, 那么就要把L1的这个元素放到最前面,至于后面的那串长啥样 ,不需要考虑. 我只要令当前的下一个节点等于下一层(令L1->next = 下一层)就行。
最终需要返回的就是当前节点加下一层。
代码如下
- 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;
- }
- else
- {
- list2->next = mergeTwoLists(list1, list2->next);
- return list2;
- }
- }