题目
解法一:暴力遍历
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
if(head==NULL)return NULL;
if(head->val==val&&head->next==NULL)return NULL;
ListNode *p=head;
ListNode *p1;
while(p->next)//删除所有值为val的节点,但结果可能会剩一个val节点
//如果删除的节点在中间,则只有这一个循环便可以解决
{
//p1=p;如果节点在中间,则用p1标记p的前驱结点
if(p->val==val)
{
p->val=p->next->val;
p->next=p->next->next;
}
else
{
p=p->next;
}
}
p1=head;
if(head->val==val)return NULL;
if(p->val==val)//如果剩余一个val节点,则找到前驱节点,把这个节点删除
{
while(p1->next!=p)
{
p1=p1->next;
}
p1->next=NULL;
}
return head;
}
};
解法二:改进暴力遍历
突然想到我可以把上面的p1和p结合起来,直接删除p1,这样只要不是第一个节点,之后的节点可以完全删除。最后判断第一个节点的值然后返回即可。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
if(head==NULL)return NULL;
ListNode *p=head;
while(p->next)
{
if(p->next->val==val)
{
p->next=p->next->next;
}
else p=p->next;
}
return head->val==val?head->next:head;
}
};
解法三:哨兵节点
前面的方法都需要单独考虑最后的第一个节点。所以可以添加一个哨兵节点作为头节点,这样后面的操作就统一起来了。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
ListNode *p=new ListNode(0);
p->next=head;
ListNode *pre=p;//用pre存放哨兵头节点的位置,后面用于删除返回
ListNode *cur=head;
ListNode *del;
while(cur)
{
if(cur->val==val)
{
p->next=cur->next;
del=cur;
}
else
{
p=p->next;
}
cur=p->next;
if(del!=NULL)
{
delete del;
del=NULL;
}
}
ListNode *q=pre->next;
delete pre;
return q;
}
};