只用固定头节点,代码如下
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
if(head==nullptr)//本来以为如果head为空,呢其head->next因也为空就不会进入while循环,但是报错非法访问,但是细想head都为空,和谈指针域,可能就像是数组如果没开辟空间,当想访问是就属于非法访问
return nullptr;
ListNode*p=head;
while(p->next)//要确保p->next不为空
{
if(p->next->val!=val)//如果下一个元素的值不为val,则说明可以后移
{
p=p->next;
}
else//否则直接跳过,想删除相等节点也可以,但这样浪费的空间差不多
p->next=p->next->next;
}
//因为最开始的时候直接从head->next开始判断的,要重新判断首节点
if(head->val==val)
head=head->next;
return head;
}
};
//一个点为啥把判断首元素放后面,如果放前面不就要循环了
//如果第二个val也等于val这不就寄了
//但是也可以就再也来个while循环,直到head->val!=val
注解很详细,其实还有好多方法对于链表删除,比如再建一个节点,当碰到一个节点需要被删除,就用新建的指针先记录它的指针域,但是这样你前一个元素又找不到了,这咋办?哎再循环一遍吗?
不理解的话,偷个图让大家伙看看,嘿嘿
思考一下,哎!屈服,哈哈哈。
但是为了代码的统一,不特殊处理首元素,思考加个虚拟头节点是不是也可以,哈哈哈
思路就是在建个节点node指向head,呢这样node->next不就参与战斗了,这样不用单独判断head是否存在
代码稍作修改
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
ListNode *node=new ListNode(0);
node->next=head;
ListNode *p=node;
while(p->next)//要确保p->next不为空
{
if(p->next->val!=val)//如果下一个元素的值不为val,则说明可以后移
{
p=p->next;
}
else//否则直接跳过,想删除相等节点也可以,但这样浪费的空间差不多
{
ListNode* tmp = p->next;
p->next = p->next->next;
delete tmp;
}
}
head=node->next;
delete node;
return head;
}
};
明天见,拜拜!