题目描述:
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
题目链接
方法1:遍历
新建一个链表 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;
}
方法2:递归
使用递归不需要创建一个新的链表,直接在现有的两个链表中进行排序。 如下图,现在两个链表合并的函数是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;
}
}