题目
代码
/**
* 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) {
}
};
方法一:迭代
分析
迭代方法是解决链表问题的最简单的方法,用
t
e
m
p
temp
temp 表示当前节点,题目要求删除链表中所有节点值等于特定值的节点,可以将条件转化为:
t
e
m
p
=
{
t
e
m
p
.
n
e
x
t
i
f
t
e
m
p
.
v
a
l
=
s
p
e
c
i
a
l
v
a
l
u
e
t
e
m
p
i
f
t
e
m
p
.
v
a
l
≠
s
p
e
c
i
a
l
v
a
l
u
e
temp= \begin{cases} temp.next &if\ temp.val=special\ value\\ temp &if\ temp.val\neq special\ value \end{cases}
temp={temp.nexttempif temp.val=special valueif temp.val=special value 由于链表操作当前节点容易出错,所以一般操作链表下一节点,即
t
e
m
p
.
n
e
x
t
temp.next
temp.next ,将上述公式转化为:
t
e
m
p
.
n
e
x
t
=
{
t
e
m
p
.
n
e
x
t
.
n
e
x
t
i
f
t
e
m
p
.
n
e
x
t
.
v
a
l
=
s
p
e
c
i
a
l
v
a
l
u
e
t
e
m
p
.
n
e
x
t
i
f
t
e
m
p
.
n
e
x
t
.
v
a
l
≠
s
p
e
c
i
a
l
v
a
l
u
e
temp.next = \begin{cases} temp.next.next &if\ temp.next.val=special\ value\\ temp.next &if\ temp.next.val\neq special\ value \end{cases}
temp.next={temp.next.nexttemp.nextif temp.next.val=special valueif temp.next.val=special value 当
t
e
m
p
.
n
e
x
t
=
n
u
l
l
temp.next=null
temp.next=null 时,链表遍历结束。
特殊情况: 由于操作的是
t
e
m
p
.
n
e
x
t
temp.next
temp.next,无法实现方面对链表的头节点
h
e
a
d
head
head 的删除操作,因此需要在当前头节点
h
e
a
d
head
head 前连接一个虚拟头节点
v
i
r
t
u
a
l
H
e
a
d
virtualHead
virtualHead,从虚拟头节点开始遍历链表,最后返回
v
i
r
t
u
a
l
H
e
a
d
virtualHead
virtualHead。
代码
/**
* 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* virtualHead = new ListNode(0, head);
ListNode* temp = virtualHead;
while(temp->next != nullptr) {
if(temp->next->val == val) {
temp->next = temp->next->next;
} else {
temp = temp->next;
}
}
return virtualHead->next;
}
};
复杂度分析
- 时间复杂度: O ( n ) O(n) O(n),其中 n n n 是链表的长度,迭代需要遍历链表每个节点。
- 空间复杂度: O ( 1 ) O(1) O(1)。
方法二:递归
分析
链表题目一般都可以用递归方法来解,先递归到达链表末端进行处理,再将处理完的链表逐级返回链表前端。可以将条件转化为:
{
r
e
t
u
r
n
n
o
d
e
.
n
e
x
t
i
f
n
o
d
e
.
v
a
l
=
s
p
e
c
i
a
l
v
a
l
u
e
r
e
t
u
r
n
n
o
d
e
i
f
n
o
d
e
.
v
a
l
≠
s
p
e
c
i
a
l
v
a
l
u
e
\begin{cases} return\ node.next &if\ node.val=special\ value\\ return\ node &if\ node.val\neq special\ value \end{cases}
{return node.nextreturn nodeif node.val=special valueif node.val=special value
代码
/**
* 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) return head;
head->next = removeElements(head->next, val);
return head->val == val ? head->next : head;
}
};
复杂度分析
- 时间复杂度: O ( n ) O(n) O(n),其中 n n n 是链表的长度。
- 空间复杂度: O ( n ) O(n) O(n),空间复杂度主要取决于递归调用栈,最多不会超过 n 层。