本题目来源于leetcode 21.合并两个有序链表
提示:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){
}
这里我们要有2个指针,分别都指空
- 为什么要一个head,因为要返回头指针
- 为什么要一个tail,因为要方便尾插
比较是用一个
L1
和一个L2
指针分别指向原来两个链表的头节点
l1
指向下一个指针然后新链表的head
不动,tail
指针指向这一个节点,即叫做尾指针的意思先要防止传进来的而指针是空的
//注意第一次凡是有空指针也会崩
//如果为空直接返回另外一个就可以了
if(l1==NULL)
{
return l2;
}
if(l2==NULL)
{
return l2;
}
这里,头插最好不要放在while
循环里面,在循环之前解决掉就可以了
if(l1->val<l2->val)
{
head=tail=l1;
l1=l1->next;
}
else
{
head=tail=l2;
l2=l2->next;
}
while循环不断走直到最后走到由一个指针NULL
while(l1&&l2)
{
//取小的尾插到新链表
if(l1->val<l2->val)
{
tail->next=l1;
l1=l1->next;
}
else
{
tail->next=l2;
l2=l2->next;
}
//tail走到新的位置上
tail=tail->next;
}
当由一个为空时把另外一个连到新链表上然后,返回头指针
//l2为空
if(l1)
{
tail->next=l1;
}
//l1为空
if(l2)
{
tail->next=l2;
}
return head;
struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){
//注意第一次凡是有空指针也会崩
if(l1==NULL)
{
return l2;
}
if(l2==NULL)
{
return l1;
}
struct ListNode* head=NULL;
struct ListNode* tail=NULL;
//第一次不要放在循环里面
if(l1->val<l2->val)
{
head=tail=l1;
l1=l1->next;
}
else
{
head=tail=l2;
l2=l2->next;
}
while(l1&&l2)
{
//取小的尾插到新链表
if(l1->val<l2->val)
{
tail->next=l1;
l1=l1->next;
}
else
{
tail->next=l2;
l2=l2->next;
}
//tail走到新的位置上
tail=tail->next;
}
//l2为空
if(l1)
{
tail->next=l1;
}
//l1为空
if(l2)
{
tail->next=l2;
}
return head;
}
另一个带头节点法:
//创建一个哨兵位头节点
struct ListNode* head=NULL;
struct ListNode* tail=NULL;
head =tail=(struct ListNode*)malloc(sizeof(struct ListNode));
tail->next=NULL;//防止两个都是空的,方便尾插
while(l1&&l2)
{
//取小的尾插到新链表
if(l1->val<l2->val)
{
tail->next=l1;
l1=l1->next;
}
else
{
tail->next=l2;
l2=l2->next;
}
tail=tail->next;
}
//l2为空
if(l1)
{
tail->next=l1;
}
//l1为空
if(l2)
{
tail->next=l2;
}
struct ListNode* node=head;
head=head->next;
free(node);
return head;
这是遇到的第一道难度为中等的题
本题目来源于leetcode 分割链表
提示:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* partition(struct ListNode* head, int x){
}
假如给出这样的例子,虽说原题没有要求说顺序不变,但是这里用牛客网的要求做试试看
那么这时我们的答案应该是,因为要求了相对顺序是不能变的,所以最后输出就是这样
把小于x的尾插到一个链表,再把大于x的尾插到一个链表,最后连接两个链表
按照第一次的思路按部就班地做
struct ListNode* partition(struct ListNode* head, int x){
struct ListNode* lessHead,*lessTail,*greaterHead,*greaterTail;
lessHead=lessTail=(struct ListNode*)malloc(sizeof(struct ListNode));
greaterHead=greaterTail=(struct ListNode*)malloc(sizeof(struct ListNode));
lessTail->next=NULL;
greaterTail->next=NULL;
struct ListNode*cur=head;
while(cur)
{
if(cur->val<x)//只处理<的
{
lessTail->next=cur;
lessTail=lessTail->next;
}
else
{
greaterTail->next=cur;
greaterTail=greaterTail->next;
}
cur=cur->next;
}
//连接两个链表
lessTail->next=greaterHead->next;
head=lessHead->next;
free(lessHead);
free(greaterHead);
return head;
}
这样说明出现问题,就要改进一下
一般时间超限原因是出现死循环
内存超限有时候是因为其他原因导致,这道题不是因为这里超过内存复杂度问题,应该想一下极端情况
这个情况是很难想到的,需要多多体会
我们将 greater 的 next指针置空,这是因为当前节点复用的是原链表的节点,而其 next指针可能指向一个小于 x 的节点,这样就会形成环,我们需要切断这个引用。
正是因为死循环所以才会报错
解决方法就是把最后一个节点置空
//关键
greaterTail->next=NULL;
struct ListNode* partition(struct ListNode* head, int x){
struct ListNode* lessHead,*lessTail,*greaterHead,*greaterTail;
lessHead=lessTail=(struct ListNode*)malloc(sizeof(struct ListNode));
greaterHead=greaterTail=(struct ListNode*)malloc(sizeof(struct ListNode));
lessTail->next=NULL;
greaterTail->next=NULL;
struct ListNode*cur=head;
while(cur)
{
if(cur->val<x)//只处理<的
{
lessTail->next=cur;
lessTail=lessTail->next;
}
else
{
greaterTail->next=cur;
greaterTail=greaterTail->next;
}
cur=cur->next;
}
//连接两个链表
lessTail->next=greaterHead->next;
//关键
greaterTail->next=NULL;
head=lessHead->next;
free(lessHead);
free(greaterHead);
return head;
}
小结:
这道题其实还有多种解法,有兴趣可以看一下多题解
这篇题目就到此为止,大家觉得有收获就请一键三连,谢谢