题目来源:力扣
题目描述:给你一个链表的头节点 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 输出:[]
示例 3:
输入:head = [7,7,7,7], val = 7 输出:[]
代码1:
struct ListNode* removeElements(struct ListNode* head, int val){
struct ListNode* prev=NULL;
struct ListNode* cur=head;
while(cur){
if(cur->val!=val){
prev=cur;
cur=cur->next;
}else{
if(prev==NULL){
head=cur->next;
free(cur);
cur=head;
}else{
prev->next=cur->next;
free(cur);
cur=prev->next;
}
}
}
return head;
}
思路:我们逐段进行分析
我们使用两个指针,一前一后
使cur先指向头,prev在cur之前(最开始为空),然后我们对cur的val进行判断,如果cur的val不等于题给的val,说明不需要删除该节点,我们让prev=cur,然后cur指向next即可,若cur的val与题给val相等,说明需要删除节点,我们让prev的next指向cur的next(prev在cur之前),然后我们释放掉cur,接着让cur指向prev的next即可,如果我们此时提交,就会发现有错误,示例3是过不了的,我们对代码进行解析,发现最开始时cur的val就等于val,此时进入循环,prev的next需要进行指向,但此时的prev为空,所以会出现空指针问题,也就是说,我们有可能需要进行头删,所以我们再次进行判断,即else里我们加的if,如果prev为空,我们进行头删。让head指向cur的next,然后释放cur,cur再指向head即可
代码2
struct ListNode* removeElements(struct ListNode* head, int val){
//if(head==NULL){
// return NULL;
//}
struct ListNode* newhead=NULL;
struct ListNode* cur=head;
struct ListNode* tail=NULL;
while(cur){
if(cur->val!=val){
if(newhead==NULL){
newhead=tail=cur;
}else{
tail->next=cur;
tail=tail->next;
}
cur=cur->next;
}else{
struct ListNode* next=cur->next;
free(cur);
cur=next;
}
}
if(tail)
{
tail->next=NULL;
}
return newhead;
}
思路:
我们创建一个新节点为新的头节点,将符合条件的节点尾插到新节点,最后返回即可
我们创建newhead和cur,还有tail节点,tail是用来指向newhead的尾节点,不然每次我们都要遍历新链表,我们对原链表进行遍历,如果val不等于cur的val,说明要将该节点尾插到newhead,不过在尾插前,我们要先判断是否为第一个节点,即newhead和tail都为NULL,此时我们要单独处理,其余情况我们将tail的next指向cur,然后tail向后移动即可,最后再让cur向后移动,如果不等于,说明要删除该节点,我们先保存cur的next,然后释放cur,cur指向next即可,我们此时提交,会出现错误,如果最后一个节点是我们要删除的,那么最后tail的next是有问题的,所以我们最后单独处理,将tail的next置为空即可,我们再次提交的话,还是会出现问题,空链表无法处理,我们对其单独处理,即前三行我屏蔽的代码,接着再次提交,示例3出现问题,我们分析知道,全部删除的话,最后newhead和tail都为空,所以我们最后对tail进行判断,如果tail不为空,也就是说我们的newhead是有节点的,我们将tail的next置为空,否则我们直接返回newhead,此时newhead为空,也就是空链表和全删除的情况我们都可以处理,所以我们删除前三行单独处理空链表的代码即可(不删也无所谓)