题目要求
删除链表中等于给定值 val 的所有节点。
解题思路
方法一:先考虑开头重复元素
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution(object):
def removeElements(self, head, val):
"""
:type head: ListNode
:type val: int
:rtype: ListNode
"""
# 先考虑开头的重复元素,使用循环处理开头的需要删除的元素
while head and head.val == val:
head = head.next
# 定义两个指针,以便删除后续需要删除的元素
now = head
if now:
nex = now.next
while now and nex:
if nex.val == val:
now.next = nex.next
else:
now = now.next
nex = nex.next
return head
方法二:哨兵节点
如果删除的节点是中间节点,问题比较容易。
但当要删除的一个或多个节点位于链表的头部时,事情会变得复杂。
因此设置哨兵节点。哨兵节点广泛应用于树和链表中,如伪头、伪尾、标记等,它们是纯功能的,通常不保存任何数据,其主要目的是使链表标准化,如使链表永不为空、永不无头、简化插入和删除。
在这里哨兵节点将被用于伪头。
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution(object):
def removeElements(self, head, val):
"""
:type head: ListNode
:type val: int
:rtype: ListNode
"""
# 设置哨兵节点
sentinel = ListNode(0)
sentinel.next = head
# 用哨兵节点初始化pre节点,head节点初始化cur节点
pre, cur = sentinel, head
while cur:
"""
最开始,head节点等于val时,一直删除之,此时pre始终跟sentinel为同一节点,
因此最终返回sentinel.next即为第一个值不等于val的节点。
"""
if cur.val == val:
pre.next = cur.next
else:
pre = cur
cur = cur.next
return sentinel.next
注意:最开始,head节点等于val时,一直删除之,此时pre始终跟sentinel为同一节点,因此最终返回sentinel.next即为第一个值不等于val的节点。
方法三:递归
此方法时间和空间复杂度较高
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution(object):
def removeElements(self, head, val):
"""
:type head: ListNode
:type val: int
:rtype: ListNode
"""
if head is None:
return head
else:
if head.val == val:
return self.removeElements(head.next, val)
else:
head.next = self.removeElements(head.next, val)
return head
知识点
注意对哨兵节点的使用。