在解决链表的很多问题时,设置快慢指针是一个很好的解决思路。
这次的问题是删除链表倒数第 n 个结点。
还有其他快慢指针的应用的问题 链表中环的检测,求单链表的中间结点 ,请点击查看。
例如, 1 -> 2 -> 3 -> 4 -> 5
,删除倒数第2个变成 1 -> 2 -> 3 -> 5
。
先看代码,再做讲解。
class Node():
def __init__(self, data, next=None):
self.data = data
self.next = next
def remove_nth_from_end(head, n):
'''删除链表倒数第 n 个结点'''
fast = head
count = 0
#第一部分
while fast and count < n:
fast = fast.next
count += 1
if not fast and count < n:
print('链表长度不足n,返回原始链表')
return head
if not fast and count == n:
return head.next
# 第二部分
slow = head
while fast.next:
fast, slow = fast.next, slow.next
slow.next = slow.next.next
return head
先让快指针fast
走n+1步,到达第n+1位置;快慢指针同时走,当快指针fast.next==None
时,慢指针slow.next
为需要删除的节点;使用slow.next = slow.next.next
删除节点后,返回head即可。
代码中需要注意两点。
- 链表长度。当
长度<n
,没有对应的可删除节点,此时返回原链表;当长度=n
,删除的倒数第n个节点正好为head节点 ;当长度>n
,执行代码第二部分。 - 指针位置。由于
count
是从0开始的,假如链表为1 -> 2 -> 3 -> 4 -> 5
,n=2
,第一部分代码结束后,fast
位置应该在3
这个位置,也就是第n+1
位。此时,设置slow = head
,开始执行。
链表如果要删除某个节点,正确的操作是上一个节点的next指向下一个节点。
比如这个例子,如果删除倒数第2个节点 4
,操作是节点3
的next指向节点5
,而不是直接对节点4
进行操作。
所以当第二部分循环结束时fast
已到尾部节点5
,slow
节点在3
,令slow.next = slow.next.next
,执行删除操作。