Method 1:
思路解析:扫描2遍-一遍数长度,一遍删除节点
for循环/while循环
class Solution:
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
root = ListNode(0)
root.next = head
#扫描一遍,算长度
a, length = head, 0
while a:
length += 1
a = a.next
#找到倒数第N个节点前一个结点
a = root
for i in range(length-n): #因为a从root开始,需要前移length-n次
a = a.next
#删除节点,重新连接
a.next = a.next.next
return root.next
Method 2:
一次扫描用递归迭代(但是并不比M1快)
class Solution:
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
if not head:
self.count = 0 #为什么为0?因为null为0才能倒数第N个为n
return head
head.next = self.removeNthFromEnd(head.next,n) #递归调用
self.count += 1
return head.next if self.count == n else head
思路解析:
带着一定要使用递归的目的,写出一行(以题目的链表为例)
因为要递归停止是为null,5->null,所以要使用head.next代表null,head代表5
class Solution:
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
head.next = self.removeNthFromEnd(head.next,n)
再次写出递归终止的条件
class Solution:
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
if not head:
self.count = 0 #为什么为0?因为null为0才能倒数第N个为n
return head
head.next = self.removeNthFromEnd(head.next,n) #递归调用
即最后一次调用,直接使5指向null,计数为0
由于
head.next = self.removeNthFromEnd(head.next,n) #递归调用
这一行head.next指向0,即head此时为5,为倒数第一个,计数+1
self.count += 1
返回的就是head(即5)
#return head.next if self.count == n else head
#我们暂时不看上面一行,依照逻辑应该写为
return head
继续
head.next = self.removeNthFromEnd(head.next,n) #递归调用
4指向上面返回的5,head为4,计数+1
但是此时self.count==2==n,不应该返回4,而应该是5
所以刚刚的加一个条件变为
return head.next if self.count == n else head
以此类推直至返回整条链表
Method 3:(双指针/快慢指针)
代码如下:
#快慢指针/双指针
class Solution:
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
root = ListNode(0)
root.next = head
#定义双指针/快慢指针
slow, fast = root, root
#快指针前移n步
length = 0
for i in range(n): #至于为什么是n步?因为当slow指向要删除节点的前一个节点时,fast要指向最后一个节点才能计数全长,而这2个节点间差n步
fast = fast.next
n += 1
#快慢指针循环前移直至fast指向最后一个节点,slow指向删除节点前一个结点
while fast.next:
slow = slow.next
fast = fast.next
n += 1
#删除节点,返回链表
slow.next = slow.next.next
return root.next