一、题目简述
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
二、题目分析
因为两个链表都是有序的,可以效仿数组中合并有序数组的方式。
在上图中,cur1代表数组a开始的位置;cur2代表数组b始的位置。
将两个位置逐一比较。
如果a[cur1]<b[cur2],那么将a[cur1]的数放到新数组中,cur1++;
如果a[cur1]>=b[cur2],那么将c[cur2]放入新数组中,cur2++;
当一个数组走完时,可能存在另一组数组未走完的情况,再将剩余的数据直接放在后面即可。
那么在链表中,也可以采用类似的方法。将val较小的节点先取下来,再继续取另一个较小的节点尾插。重复上述步骤。
当然也有可能出现链表未走完的情况,这时候直接将剩余节点链接到尾上即可。
有一个链表为空直接返回另一个链表。
三、代码分析
1、建立一个哨兵卫节点
struct ListNode* head=NULL;
struct ListNode* fhead=(struct ListNode*)malloc(sizeof(struct ListNode));//建立哨兵卫节点
fhead->next==NULL;//节点初始化
struct ListNode* tail=fhead;//尾节点
在进入循环之前,肯定要选取一个较小的节点作为头节点。如果有一个链表为NULL,那么就要会出现空指针的解引用,需要对链表进行判断。
那么可以malloc一个新的节点fhead作为哨兵节点,将tail(尾节点)置为fhead,而真正的头则是fhead->next。这样可以更方便一些,当然最后要将fhead释放掉,避免内存泄漏。
2、比较节点
while(list1&&list2)
{
if(list1->val<list2->val)//取较小节点
{
tail->next=list1;
list1=list1->next;
}
else
{
tail->next=list2;
list2=list2->next;
}
tail=tail->next;//更新尾节点
}
与数组类似,比较每一个节点。如果list1节点值较小,取list1的头节点,
进行尾插,list2节点不动,等待下一次的比较;如果list2节点较小,取list2头节点,进行尾插,list1节点不动,等待下一次比较。
每一次尾插完一个节点,tail要进行更新。list1和list2的其中一个要向后走动。
第一次比较list1节点的val较小,取下进行头插,list1向后走,list2不动。
tail更新。
第二次比较,val相等,随意取一个节点。图中取list2节点,list向后走,list1不动,tail更新。以此类推。
(如果有一个链表为NULL,显然不会进入循环)
3、链接剩余数据
if(list1)
{
tail->next=list1;//链接list1数据
}
else{
tail->next=list2;//链接list2数据
}
当有一个链表节点以及全部取下来之后,另外一个链表会有数据残留,是较大的值。
如上图所示:当list1走完后,list2中剩余较大的数据,此时直接将list2链接到fhead的尾部即可。
if(list1),list1不为空,将list1链接到尾部。
else,list2不为空,将list2链接到尾部。
head=fhead->next;//真正的头节点
free(fhead);//释放哨兵卫节点
return head;
head置为fhead->next,再将fhead释放即可。
四、完整代码
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
struct ListNode* head=NULL;
struct ListNode* fhead=(struct ListNode*)malloc(sizeof(struct ListNode));//哨兵卫节点
fhead->next==NULL;//初始化
struct ListNode* tail=fhead;//尾节点
while(list1&&list2)
{
if(list1->val<list2->val)//取较小节点
{
tail->next=list1;//链接到尾部
list1=list1->next;
}
else
{
tail->next=list2;//链接到尾部
list2=list2->next;
}
tail=tail->next;//更新尾节点
}
if(list1)//list1不为空
{
tail->next=list1;//链接list1数据
}
else //list2不为空
{
tail->next=list2;//链接list2数据
}
head=fhead->next;//真正的头节点
free(fhead);//释放哨兵卫节点
return head;
}