目录
203.移除链表元素
题目链接:. - 力扣(LeetCode)
文章讲解:代码随想录
视频讲解:手把手带你学会操作链表 | LeetCode:203.移除链表元素_哔哩哔哩_bilibili
解题卡点:没分清链表结构,例如虚拟头节点没有用类实例化,使用node.next == val进行了判断
移除链表元素,需要知道它的上一个元素。该元素需要被移除时,让上一个节点的指针指向下一个节点。即上一个节点node.next.val==val时,node.next=node.next.next。若链表头节点需被移除,将节点指针向后移动一位,也就是第二个节点作为头节点。另外也可以使用虚拟头节点法,对全列表进行统一操作。
全篇是对current_code进行处理,为什么最后的dummy_head.next是正确答案?准确的说内存中只有1个链表,虚拟头节点在创捷后接上了原链表,是1个链表,current_node是副本链表,是(虚拟头节点+原链表)的弱引用,他们指向的是同1个对象实例。由于弱引用,改变current_node的指针会让(虚拟头节点+原链表)的指针同时受到影响。为何需要current_node,不对原链表处理呢?由于node=node.next,直接使用原链表会使原链表中只有最后一个元素。下面的print(current_node)也是这一情况的体现。故对(虚拟头节点+原链表)潜复制为current_node,current_node的指针变化反映在(虚拟头节点+原链表)上,元素变化不反映在其上。
总结:链表元素的移除就是改变指针next。next里实际储存的是下一个节点的类实例。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def removeElements(self, head: Optional[ListNode], val: int) -> Optional[ListNode]:
# print(head)
dummy_head = ListNode(None, head) # 创建虚拟头节点,下一个节点是原本的头节点
current_node = dummy_head # 遍历所有节点的指针
while current_node.next: # 当前节点仍有下一个元素时继续循环
if current_node.next.val == val: # 当前节点的下一个元素为目标值时
current_node.next = current_node.next.next # 当前节点下一个节点变为下下个节点,当前节点没有变化
else:
current_node = current_node.next # 只有当前节点的下一个元素不为目标值时,当前节点才往前进一位
# print(current_node)
# print(dummy_head)
return dummy_head.next # 返回真实的头节点
# ListNode{val: 1, next: ListNode{val: 2, next: ListNode{val: 6, next: ListNode{val: 3, next: ListNode{val: 4, next: ListNode{val: 5, next: ListNode{val: 6, next: None}}}}}}}
# ListNode{val: 5, next: None}
# ListNode{val: None, next: ListNode{val: 1, next: ListNode{val: 2, next: ListNode{val: 3, next: ListNode{val: 4, next: ListNode{val: 5, next: None}}}}}}
# 时间复杂度 O(n)
# 空间复杂度 O(1)
707.设计链表
题目链接:. - 力扣(LeetCode)
文章讲解:代码随想录
视频讲解:帮你把链表操作学个通透!LeetCode:707.设计链表_哔哩哔哩_bilibili
解题卡点:
206.反转链表
题目链接:. - 力扣(LeetCode)
文章讲解:代码随想录
视频讲解:帮你拿下反转链表 | LeetCode:206.反转链表 | 双指针法 | 递归法_哔哩哔哩_bilibili
解题卡点: