移除链表元素
给你一个链表的头节点 head
和一个整数 val
,请你删除链表中所有满足 Node.val == val
的节点,并返回 新的头节点 。
思路:(1)创建三个结构体指针,分别代表一条新链表的头newhead
,一条新链表的尾newtail
,还有一个用于循环旧链表的pcur
(2)循环旧链表,当pcur
的val
不等于函数参数中的val
时:1.当新链表为空时,将新链表的newhead
和newtail
赋值为pcur
2.当新链表不为空时,newtail
的next
指向pcur
,newtail
赋值为newtial
的next
;
(3)运行完一个结点pcur
赋值为pcur
的next
(4)当运行结束时,代表旧链表运行完毕,当最后一个结点等于val
时,newtail
的值不会是空,而是旧链表最后一个结点的值,因此我们需要进行判断,当newtail
不为空时,需要将newtail
置空,最后返回newhead
即可
struct ListNode* removeElements(struct ListNode* head, int val)
{struct ListNode* newhead=NULL;struct ListNode* newtail=NULL;struct ListNode* pcur=head;while(pcur){if(pcur->val != val){if(newhead == NULL){newhead=newtail=pcur;}else{newtail->next=pcur;newtail=newtail->next;}}pcur=pcur->next;}if(newtail){newtail->next=NULL;}return newhead;
}
反转链表
给你单链表的头节点 head
,请你反转链表,并返回反转后的链表。
思路:(1)若链表为空,则直接返回空
(2)若不为空,创建三个结构体指针分别为n1,n2,n3
,将n1
赋值为NULL
,n2
赋值为head
,n3
赋值为head->next
(3)以n2
为循环条件进行遍历,每次运行都将n2
的next
赋值为n1
,n1
赋值为n2
,n2
赋值为n3
,若n3
不为空则n3
赋值为n3
的next
(下图为第一次和第二次循环图)
(4)又因为n2
和n3
最后的位置都为NULL
,所以最后返回n1
即可。
struct ListNode* reverseList(struct ListNode* head)
{if(head==NULL){return NULL;}struct ListNode* n1=NULL;struct ListNode* n2=head;struct ListNode* n3=head->next;while(n2){n2->next=n1;n1=n2;n2=n3;if(n3){n3=n3->next;}}return n1;
}
合并两个有序链表
将两个升序链表合并为一个新的升序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
思路:(1)判断传入的参数list1、list2
是否为空,为空则返回另一个
(2)创建四个结构体指针,newhead
代表新链表的头,newtail
代表新链表的尾,pcur1
和pcur2
分别用来遍历list1
和list2
(3)若pcur1
和pcur2
都不为空则进入循环,当pcur1
的val
大于pcur2
的val
,判断newhead
是否为空,为空则将newhead
和newtail
赋值为pcur1
,不为空则进行新链表结点的插入,即将newtail
的next
赋值为pcur1
,newtail
赋值为newtail
的next
;pcur1
小于等于pcur2
时同理,只需将pcur1
改为pcur2
即可
(4)当循环结束,判断pcur1
与pcur2
是否为空,某个不为空时,将newtail
的next
赋值为不为空的pcur
,最后返回newhead
即可
- 不带头单向不循环链表
//不带头单向不循环链表
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{if(list1 == NULL){return list2;}if(list2 == NULL){return list1;}struct ListNode* newhead=NULL;struct ListNode* newtail=NULL;struct ListNode* pcur1=list1;struct ListNode* pcur2=list2;while(pcur1 && pcur2){if((pcur1->val) < (pcur2->val)){if(newhead == NULL){newhead=newtail=pcur1;}else{newtail->next=pcur1;newtail=newtail->next;}pcur1=pcur1->next;}else{if(newhead == NULL){newhead=newtail=pcur2;}else{newtail->next=pcur2;newtail=newtail->next;}pcur2=pcur2->next;}}if(pcur1 != NULL){newtail->next=pcur1;} if(pcur2 != NULL){newtail->next=pcur2;}return newhead;
}
- 带头单向不循环链表
思路:(1)newhead
和newtail
的初始值不再是NULL
,而是一个没有val
值的结点,相当于是一个哨兵位。因此就不再需要判断newhead
是否为空。
(2)最后需要将malloc
的newhead
指针释放,需要创捷一个新结构体指针rehead
赋值为newhead
的next
,便可进行newhead
的释放,最后返回rehead
即可
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{if(list1 == NULL){return list2;}if(list2 == NULL){return list1;}struct ListNode* newhead=(struct ListNode*)malloc(sizeof(struct ListNode));struct ListNode* newtail=newhead;struct ListNode* pcur1=list1;struct ListNode* pcur2=list2;while(pcur1 && pcur2){if((pcur1->val) < (pcur2->val)){newtail->next=pcur1;newtail=newtail->next;pcur1=pcur1->next;}else{newtail->next=pcur2;newtail=newtail->next;pcur2=pcur2->next;}}if(pcur1 != NULL){newtail->next=pcur1;} if(pcur2 != NULL){newtail->next=pcur2;}struct ListNode* rehead=newhead->next;free(newhead);newhead=NULL;return rehead;
}
链表的中间结点
给你单链表的头结点 head
,请你找出并返回链表的中间结点。
如果有两个中间结点,则返回第二个中间结点。
思路:(1)运用快慢指针,创建两个结构体指针,分别为slow
和fast
,slow
每次走一个结点,fast
每次走两个结点(如下图)
(2)返回slow
指针即可
struct ListNode* middleNode(struct ListNode* head)
{struct ListNode* fast=head;struct ListNode* slow=head;while(fast && fast->next){slow=slow->next;fast=fast->next->next;}return slow;
}