返回
聪明学霸拆解链表巧妙删除术,快慢指针闪耀全场
前端
2024-02-07 08:43:21
巧妙解决删除链表倒数第 n 个节点的难题
概览
当你面对遍历链表的问题时,通常只能从链表头部开始,逐个遍历每个节点。然而,如果你需要删除链表中倒数第 n 个节点,就需要采取巧妙的方法来解决这个问题。本文将深入探讨两种有效的方法:快慢指针和多指针法,并提供代码示例和常见问题解答。
快慢指针法
快慢指针法是一种经典的链表遍历方法,利用两个指针——快指针和慢指针——以不同速度遍历链表。快指针先走 n 步,然后快慢指针同时遍历链表。当快指针到达链表末尾时,慢指针恰好指向倒数第 n 个节点。
def remove_nth_from_end(head, n):
"""
删除链表中倒数第 n 个节点。
Args:
head: 链表的头节点。
n: 要删除的节点的位置。
Returns:
链表的头节点。
"""
# 创建快慢指针。
fast = head
slow = head
# 快指针先走 n 步。
for _ in range(n):
fast = fast.next
# 当快指针到达链表的末尾时,慢指针就指向了倒数第 n 个节点。
while fast is not None:
fast = fast.next
slow = slow.next
# 删除倒数第 n 个节点。
slow.next = slow.next.next
# 返回链表的头节点。
return head
多指针法
多指针法是另一种有效的链表遍历方法,使用多个指针同时遍历链表。在这个场景中,可以使用两个指针,一个指向倒数第 n 个节点,另一个指向倒数第 n+1 个节点。当倒数第 n+1 个节点到达链表末尾时,倒数第 n 个节点就指向了倒数第 n 个节点。
def remove_nth_from_end(head, n):
"""
删除链表中倒数第 n 个节点。
Args:
head: 链表的头节点。
n: 要删除的节点的位置。
Returns:
链表的头节点。
"""
# 创建两个指针,一个指向倒数第 n 个节点,另一个指向倒数第 n+1 个节点。
p = head
q = head
# 倒数第 n 个节点走 n 步。
for _ in range(n):
q = q.next
# 当倒数第 n+1 个节点到达链表的末尾时,倒数第 n 个节点就指向了倒数第 n 个节点。
while q is not None:
p = p.next
q = q.next
# 删除倒数第 n 个节点。
p.next = p.next.next
# 返回链表的头节点。
return head
结论
无论采用快慢指针法还是多指针法,都可以高效地删除链表中倒数第 n 个节点。这两种方法都很实用,在不同的场景下都可以选择合适的方法来解决问题。
常见问题解答
- 为什么需要删除链表中的倒数第 n 个节点?
在实际应用中,可能有各种原因需要删除链表中的倒数第 n 个节点。例如,在实现缓存系统时,需要删除最不经常使用的节点(链表的倒数第 n 个节点),以释放内存空间。
- 这两种方法有什么优缺点?
快慢指针法比较简单易懂,实现也相对简单。而多指针法虽然代码稍复杂,但它可以同时遍历链表中的多个位置,在某些场景下效率更高。
- 如果链表的长度小于 n,应该如何处理?
如果链表的长度小于 n,则倒数第 n 个节点不存在。在这种情况下,通常会返回原始链表。
- 是否可以一次删除链表中多个倒数第 n 个节点?
可以,但需要修改算法以一次删除多个节点。一种方法是使用多重指针,每个指针指向不同的倒数第 n 个节点。
- 这两种方法是否适用于循环链表?
快慢指针法适用于循环链表,而多指针法不适用于循环链表,因为循环链表中不存在倒数第 n 个节点。