方法一:迭代 双指针法
1.1:最基础解法
时间复杂度:O(n)
空间复杂度:O(1)
class Solution
{
public:
ListNode* removeElements(ListNode* head, int val)
{
ListNode* prev = nullptr; //我们用两个指针来遍历链表
ListNode* curr = head;
if (head == nullptr) //首先判断链表是否为空
{
return nullptr;
}
if (head->next == nullptr) //其次判断链表是否只有一个节点
{
if (head->val == val) //以及这个节点是否要删除
{
delete head;
return nullptr;
}
return head;
}
while (curr != nullptr)
{
if (curr->val == val)
{
if (prev == nullptr) //如果为true,说明头节点要删除
{
head = head->next; //这里是对头节点删除的特殊操作
delete curr;
curr = head;
}
else
{
prev->next = curr->next; //这里是对普通节点的删除的一般操作
delete curr;
curr = prev->next;
}
}
else //为false,说明不用删除,那我们移动到下一个节点
{
prev = curr;
curr = curr->next;
}
}
return head;
}
};
1.2:虚拟头节点法
1.1方法太过麻烦,因为对头节点的操作很特殊,所以我们虚拟一个头节点,这样对头节点的操作也可以一般化了
时间复杂度:O(n)
空间复杂度:O(1)
class Solution
{
public:
ListNode* removeElements(ListNode* head, int val)
{
ListNode* newNode = new ListNode(-1, head); //虚拟头节点,指向头节点
ListNode* prev = newNode;
ListNode* curr = head;
while (curr != nullptr)
{
if (curr->val == val) //所有删除操作都可由如下操作完成,统一了所有的情况
{
prev->next = curr->next;
delete curr;
curr = prev->next;
}
else
{
prev = curr;
curr = curr->next;
}
}
return newNode->next; //即为head
}
};
方法二:递归
时间复杂度:O(n)
空间复杂度:O(n)
class Solution
{
public:
ListNode* removeElements(ListNode* head, int val)
{
if (head == nullptr) //说明已经过了最后一个节点了
{
return nullptr;
}
head->next = removeElements(head->next, val);
if (head->val == val)
{
ListNode* next = head->next;
delete head;
return next;
}
return head;
}
};