定义


1
2
3
4
type LinkNode struct{
Val int
Next *LinkNode struct
}

移除链表元素


给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点

示例 1:

img

1
2
输入:head = [1,2,6,3,4,5,6], val = 6
输出:[1,2,3,4,5]

示例 2:

1
2
输入:head = [], val = 1
输出:[]

示例 3:

1
2
输入:head = [7,7,7,7], val = 7
输出:[]

我的答案:

我是设置了p,q两个指针,一前一后

比较的时候要用后面的指针进行比较,因为删除操作要跳跃一个元素

因为删除元素的地方要分为 头部,中间,尾部三个地方,所以我特地分了三种情况(看了标准答案后发现我是傻逼,因为某个写法跟我很相似,但是能囊括三种情况)

整体代码有冗余,还很长,看一下标准版本的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
func removeElements(head *ListNode, val int) *ListNode {
// 判断第一个节点是不是空
if head==nil{
return head
}
// 用循环保证第一个节点没有空
for head.Val == val {
head = head.Next
if head == nil {
return head
}
}
p := head
q := p.Next
for q !=nil{
if q.Val==val{
// 表示不是最后一个节点的情况
if q.Next != nil{
p.Next=q.Next
q = p.Next
continue
}else{//表示最后一个节点的情况
p.Next=nil
break
}
}
p = p.Next
q = p.Next
}
return head
}

标准答案:

这边dummyHead表示的是一个头指针。

这里用cur 与 cur.Next表示一前一后的指针关系,这边的重点就是两个指针指向

看这边也是用后面的指针cur.Next来比较,可见设置前置指针的重要性

考虑一下情况,if的条件前中后都能实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
func removeElements(head *ListNode, val int) *ListNode {
dummyHead := &ListNode{}
dummyHead.Next = head
cur := dummyHead
for cur != nil && cur.Next != nil {
if cur.Next.Val == val {
cur.Next = cur.Next.Next
} else {
cur = cur.Next
}
}
return dummyHead.Next
}