题目描述
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
代码示例
from typing import Optional
# 定义单链表节点
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class Solution:
def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
# 创建一个虚拟节点来处理需要移除头节点的边缘情况
dummy_head = ListNode(val=0, next=head)
fast_pointer = slow_pointer = dummy_head
# 将快指针提前移动 n+1 步
n += 1
while n > 0 and fast_pointer:
fast_pointer = fast_pointer.next
n -= 1
# 同时移动指针直到快指针到达链表末尾
while fast_pointer:
slow_pointer = slow_pointer.next
fast_pointer = fast_pointer.next
# 从末尾移除第 n 个节点
slow_pointer.next = slow_pointer.next.next
return dummy_head.next
# 示例:创建一个链表并从末尾移除第二个节点
if __name__ == "__main__":
# 辅助函数:从值列表创建链表
def create_linked_list(values):
if not values:
return None
head = ListNode(values[0])
current = head
for val in values[1:]:
current.next = ListNode(val)
current = current.next
return head
# 辅助函数:打印链表
def print_linked_list(head):
while head:
print(head.val, end=" -> ")
head = head.next
print("None")
# 创建链表:1 -> 2 -> 3 -> 4 -> 5
linked_list = create_linked_list([1, 2, 3, 4, 5])
print("原始链表:")
print_linked_list(linked_list)
# 从末尾移除第二个节点
sol = Solution()
modified_list = sol.removeNthFromEnd(linked_list, 2)
# 打印修改后的链表
print("\n移除节点后的链表:")
print_linked_list(modified_list)
在面对删除链表倒数第n个节点的问题时,一开始的直观思考是遍历整个链表,找到最后一个节点,然后返回找到对应节点的前一个节点。但是由于这是一个单链表,我们需要提前知道链表的长度,再进行一次遍历找出要删除的节点,并将其移除。
然而,通过学习完整个代码随想录后,我发现可以采用快慢指针的方式来更加巧妙地解决问题。通过让快指针先走n步,然后慢指针开始走,当快指针到达链表末尾时,慢指针正好走到要移除的节点上。这样,我们可以在删除节点之前的节点上进行操作。让快指针先走n+1步,慢指针正好落在移除节点之前的节点上。
在实现过程中遇到的困难是,初始时快指针和慢指针的位置都指向了dummy.next,导致了错误的发生。为了避免这个问题,我修改了初始的指针位置,
总的来说,通过这个问题的学习,我不仅学会了如何使用快慢指针处理链表问题,而且发现了创建dummy_head节点的妙用,简化了链表操作,省去了原有链表中的一些繁琐操作。这次学习让我更深入地理解了链表的操作技巧,也提高了解决类似问题的能力。在学习的过程中,我意识到快慢指针的应用不仅局限于数组,同样可以在链表中发挥巨大的作用。