203. 移除链表元素
https://leetcode-cn.com/problems/remove-linked-list-elements/
难度简单502收藏分享切换为英文接收动态反馈
删除链表中等于给定值 val 的所有节点。
示例:
输入: 1->2->6->3->4->5->6, val = 6
输出: 1->2->3->4->5
解法1 蛮力操作 删除
为了方便测试给出一些辅助测试函数
create_linked_list
创建链表
print_linked_list
打印链表
from typing import List, Optional
# Definition for singly-linked list.
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
def create_linked_list(array: List, n: int) -> Optional[ListNode]:
"""
:param array: linked list node value
:param n: length of array
:return:
"""
if not array:
return None
head = ListNode(array[0])
p = head
for i in range(1, n):
p.next = ListNode(array[i])
p = p.next
return head
def print_linked_list(head: ListNode):
while head:
print(f'{head.val} ->', end=' ')
head = head.next
print('NULL')
删除的元素如果就是头节点的情况,需要单独的考虑。
删除头节点的情况
删除任意节点的情况
下面给出解题代码 :
第一种暴力解法
class Solution:
def removeElements(self, head: ListNode, val: int) -> ListNode:
# 处理头结点 是要删除的节点的情况
while head and head.val == val:
delnode= head
head = delnode.next
# 开始删除 头结点的下一个节点
cur = head
while cur and cur.next:
if cur.next.val == val:
delnode = cur.next
cur.next = delnode.next
del delnode
else:
cur = cur.next
return head
第二种暴力解法:
相对第一种解法 : 类似,只是 删除节点的 判断条件 稍微变化了一下。
因为 我们需要找到 cur.next 的值 是不是等于val , 所以while 的条件 进来的时候 ,就判断cur.next
是否存在即可。这里不需要担心 cur
这个节点是否为空的问题, 因为前面处理完head
节点了。 head 节点不可能为空值。
这里要好好体会下, 如果有效的进行控制判断条件。这种写法看起来更加精妙。
一般我们在 链表中如果访问一个结点, 就需要进行判定空的判断, 否则很容易出现. 访问了一个空节点的next
的这种情况。 类似 if cur and cur.next
判断,否则 很容易出现访问空节点的情况。
class Solution:
"""
头结点 暴力删除
"""
def removeElements(self, head: ListNode, val: int) -> ListNode:
# 处理头结点 是要删除的节点的情况
while head is not None and head.val == val:
delnode = head
head = delnode.next
# 处理完成后,继续判断 head 是否为空
if head is None:
return None
# 开始删除 头结点的下一个节点
cur = head
while cur.next:
if cur.next.val == val:
delnode = cur.next
cur.next = delnode.next
else:
cur = cur.next
return head
if __name__ == '__main__':
# array = [1, 1, 1, 2, 3, 1, 1, 4, 5, 6, 1,1]
array = [1, 1, 1]
head = create_linked_list(array=array, n=len(array))
print_linked_list(head)
h2 = Solution().removeElements(head, 1)
print_linked_list(h2)
解法2 建立虚拟头节点
通过建立虚拟头节点 ,保证链表的删除的操作是统一的. 防止 删除的结点刚好在头节点上, 要进行特殊的处理。
有了虚拟头结点, 我们处理链表 就不需要考虑是不是 删除的节点是否在头节点
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def removeElements(self, head: ListNode, val: int) -> ListNode:
# 构建虚拟头节点
dummy_head = ListNode('dummy')
dummy_head.next = head
cur = dummy_head
while cur.next:
if cur.next.val == val:
delnode = cur.next
cur.next = delnode.next
del delnode
else:
cur = cur.next
result = dummy_head.next
# 删除虚拟头节点
del dummy_head
return result
解法3 递归法
本着 万事皆可递归的原则 ,链表本身就是一种可递归的结构,和二叉树相比较而言,只是链表只有一个next 指针,而二叉树有两个指针而已.
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def removeElements(self, head: ListNode, val: int) -> ListNode:
# terminator
if head is None:
return None
# drill down
head.next = self.removeElements(head.next, val)
# current level logic process
if head.val == val:
return head.next
else:
return head