🚗题目描述
给你一个链表的头节点
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.明确递归方法要实现什么功能? --删除元素值为val的结点
2.明确递归开始结束的条件?--当head指针为nullptr时终止
3.返回给上一级什么值?--返回处理后的头结点
图释:
class Solution{
public:
ListNode* removeElements(ListNode* head,int val){
//边界条件:空链表
if(head==nullptr){return nullptr;}
head->next=removeElements(head->next,val);
//对每个头结点进行处理:删除值为val的结点
if(head->val==val){
ListNode* p=head;
head=head->next;
delete p;
return head;
}
//返回头结点
return head;
}
};
🥖解法二:迭代法
遍历链表找到元素值为val的结点,将值为val的结点的上一结点指向值为val的结点的下一结点,注意头结点值为val的情况,用while(pre->next!=nullptr)循环解决
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
//判断头结点是否为val值,采用头删法
while(head!=nullptr&&head->val==val)
{
head = head->next;//头删法
}
//判断链表是否为空
if(head==nullptr){return head;}
//遍历链表删除等于val值的结点
ListNode* pre= head;
while(pre->next != nullptr){
if(pre->next->val==val)
{
pre->next=pre->next->next;
}else{
pre=pre->next;
}
}
return head;
}
};
🥖解法三:双指针法
先解决头结点值为val的特殊情况,采用头删法,利用while循环head=head->next
设置pre和arc两个指针并初始化指向head,arc往后扫描,若元素值不为val,则将pre指针移到arc(pre=arc)保证pre跟在arc后面,若arc指向的元素值为val,则将pre的下一个指向arc的下一个不为val值的元素,当arc为空时结束while循环。
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
while(head!=nullptr&&head->val==val)
{
head=head->next;//头删法
}
ListNode* pre=head;
ListNode* arc=head;
while(arc){
if(arc->val==val)
{
pre->next=cur->next;
}else{
pre=arc;
}
arc=arc->next;
}
return head;
}
};
🥖解法四:哨兵(虚拟头结点)
通过在头节点前增加虚拟头节点(哨兵),头结点则变为普通结点,则不需要判断头节点是否为待删除的节点,但是在返回的时候需要返回的是虚拟头节点的下一节点而不是虚拟头节点。
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
//增加虚拟头结点
ListNode* dummyHead = new ListNode(0,head);
ListNode* cur = dummyHead;
while(cur->next){
if(cur->next->val==val){
cur->next=cur->next->next;
}else{
cur=cur->next;
}
}
ListNode* ret=dummyHead->next;
delete dummyHead;
return ret;
}
};
--------以上为四种解题思路,仅供参考~