目录
一、合并两个有序链表
题目介绍:
题目提供了两个升序链表,需要进行合并后,返回合并后的升序链表。
题目思路:
遍历题目的两个有序链表,将其对应的val值进行比较,将val值小的结点取下来,尾插到新建的链表中,不断重复直到遍历完链表。
代码实现:
解法1:不带哨兵位的头结点
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
struct ListNode*head=NULL,*tail=NULL;//建立head与tail
//如果其中一个为空,返回另一个
if(list1==NULL)
{
return list2;
}
if(list2==NULL)
{
return list1;
}
//先取一个小的去做新链表的第一个结点
if(list1->val>list2->val)
{
head=tail=list2;//尾插
list2=list2->next;//指向下一个
}
else
{
head=tail=list1;
list1=list1->next;
}
while(list1 && list2)//有一个链表为空时循环结束
{
//比较大小
if(list1->val>list2->val)
{
tail->next=list2;//尾插到tail
tail=list2;//改变尾
list2=list2->next;//指向下一个
}
else
{
tail->next=list1;
tail=list1;
list1=list1->next;
}
}
//判断哪个链表先走完,剩下的直接插到新链表后面即可
if(list1)
{
tail->next=list1;
}
if(list2)
{
tail->next=list2;
}
return head;
}
解法2:带哨兵位的头结点
上述解法中,需要对第一次插入进行分开解决,而建立一个带哨兵位的头结点则不需要对第一次插入进行分开解决。
哨兵位的链表与不带哨兵位的链表有何区别?
如图所示,带哨兵位的头结点最大的不同就是其头结点不存储有效数据。
代码实现:
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
struct ListNode*head=NULL,*tail=NULL;//建立head与tail
//带哨兵位的头结点
tail=head=(struct ListNode*)malloc(sizeof(struct ListNode));//开辟空间
//如果其中一个为空,返回另一个
if(list1==NULL)
{
return list2;
}
if(list2==NULL)
{
return list1;
}
while(list1 && list2)//有一个链表为空时循环结束
{
//比较大小
if(list1->val>list2->val)
{
tail->next=list2;//尾插到tail
tail=list2;//改变尾
list2=list2->next;//指向下一个
}
else
{
tail->next=list1;
tail=list1;
list1=list1->next;
}
}
//判断哪个链表先走完,剩下的直接插到新链表后面即可
if(list1)
{
tail->next=list1;
}
if(list2)
{
tail->next=list2;
}
struct ListNode*list=head->next;
free(head);//释放开辟的空间
return list;
}
总结:
解法1虽然需要对第一次插入进行分开解决,但是不需要动态开辟内存,同时也不需要释放空间;
解法2不需要对第一次插入进行分开解决,但是需要开辟空间,还有释放空间。两者各有优缺点。