题目一.移除链表元素
203. 移除链表元素https://leetcode.cn/problems/remove-linked-list-elements/
给你一个链表的头节点 head
和一个整数 val
,请你删除链表中所有满足 Node.val == val
的节点,并返回 新的头节点 。
示例 1: 输入:head = [1,2,6,3,4,5,6], val = 6 输出:[1,2,3,4,5]示例 2:
输入:head = [], val = 1 输出:[]
1.思路分析
在查询链表内与待删数据val相同结点时,存在几种边界情况,需要分类考虑:
a.链表为空 head==nullptr
b.链表非空 (1).表头结点数据域与val相同,涉及头指针移动。
(2).表内某一位置结点的数据域与val相同,修改指针即可。
(3).表尾结点数据域与val相同,其前趋结点指针置nullptr即可。
若不是上述情况,指针后移查询。
此外,为了单链表删除方便,设置一个辅助指针q,总指向待删结点的前趋,以方便操作
2.AC代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeElements(struct ListNode* head, int val){
if(head==NULL) return NULL;
else{
struct ListNode* p=head->next;
struct ListNode* q=head;
while(head!=NULL&&head->val==val) {
head=head->next;
}
if(head!=NULL) p=head->next;
q=head;
while(p!=NULL&&q!=NULL){
if(p->val==val){
if(p->next==NULL){
q->next=NULL;
p=NULL;
}
else {
q->next=p->next;
p=p->next;
}
}
else {
q=q->next;
p=p->next;
}
}
}
return head;
}
题目二.反转链表
206. 反转链表https://leetcode.cn/problems/reverse-linked-list/
给你单链表的头节点 head
,请你反转链表,并返回反转后的链表。
示例 1:
输入:head = [1,2,3,4,5] 输出:[5,4,3,2,1]
示例 2:
输入:head = [1,2] 输出:[2,1]
1.思路分析
反转链表思路很多,在此开门见山,选择最直接清晰的方法:“头插法”;即遍历原单链表,将每一个结点的数据域赋值到新结点内,插入表头,这样遍历之后,新表自然为倒序。
且要注意的是,如果从空间复杂度上考虑,不新建结点,而是将原链表结点直接送入新链表,则要先保存原遍历指针,再后移遍历指针。最后在保存的位置上进行指针交接,否则会使链表断裂。
2.AC代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* reverseList(struct ListNode* head){
struct ListNode* newhead=NULL;
if(head==NULL) return NULL;
else{
struct ListNode* p=head;
while(p!=NULL){
struct ListNode* s=(struct ListNode*)malloc(sizeof(struct ListNode));
s->val=p->val;
s->next=newhead;
newhead=s;
p=p->next;
}
}
return newhead;
}
题目三.删除链表中的重复元素
83. 删除排序链表中的重复元素https://leetcode.cn/problems/remove-duplicates-from-sorted-list/
给定一个已排序的链表的头 head
, 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。题目数据保证链表已经按升序 排列
示例 1:
输入:head = [1,1,2] 输出:[1,2]
示例 2:
输入:head = [1,1,2,3,3] 输出:[1,2,3]
1.思路分析
解决链表去重问题的方法多种多样,在此讨论思路最简单清晰的一种方法:“后继法”,由于本题限定条件为链表递增,则重复数据必然在一系列相邻的结点内。
若相邻两个数不相同,则链表后续不可能再出现与第一个数重复的结点。
故设置两个相邻指针:p、q(q指向p后继)。
a.若p->val!=q->val,则两个相邻指针同速度后移,保持相邻。
b.若p->val==q->val:(1).q后继为空,直接将p的next域置nullptr,
(2).q后继非空,交接指针,q后移而p不移动,以防多个相邻重复元素。
如测试数据[1,1,1,1,2,3,4,5,5,5]
2.AC代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* deleteDuplicates(struct ListNode* head){
if(head==NULL) return NULL;
else if(head!=NULL&&head->next==NULL) return head;
else{
struct ListNode* p=head;
struct ListNode* q=head->next;
while(p!=NULL){
while(q!=NULL){
if(p->val==q->val) {
if(q->next!=NULL) p->next=q->next;
else p->next=NULL;
q=q->next;
}
else {
q=q->next;
break;
}
}
p=p->next;
}
return head;
}
}