我的思路就是先遍历一遍获得总长度,将倒数第N结点,换成正数的第m = len - n + 1个结点,然后从头遍历到第m个结点,删除即可。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
if head.next == None: # 特殊情况1:长度为1
return None
# 长度>=2
q = head.next
pre = head
Llen = 2
# 获得链表的长度
while q.next:
Llen += 1
pre = q # 记录前一个节点
q = q.next # 后移
# pre 指向倒数第二个节点,q指向最后一个节点
m = Llen - n + 1 # 删除正数第m个数
if m == Llen: # 特殊情况2:删除最后一个数 ,n=1
pre.next = None
# 删除节点p
return head
if m == 1: # 特殊情况3:删除第一个数,n=Len # 删除第一个节点
head = head.next
return head
# 情况4:删除中间节点
count = 1
q = head.next
pre = head
while q:
count += 1
if count == m:
pre.next = q.next
# 删除q
pre = q
q = q.next
return head
但如果要求只遍历一遍,怎么实现呢?
可以参考官方的解析用栈或者两个指针。
我觉得栈应该也算两次遍历
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
# 比我的代码简洁多了,而且还通用。引入dummy作为头指针的前驱指针
dummy = ListNode(0,head) # 头指针的前一个指针
stack = list() # 栈
cur = dummy
while cur: # 全部遍历入栈
stack.append(cur)
cur = cur.next
for i in range(n): # 计数出栈
stack.pop() # 弹出n个后,此时顶端是倒数第n个指针的前一个指针,为了方便删除操作
prev = stack[-1]
prev.next = prev.next.next
return dummy.next
用双指针才算只遍历一次
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
dummy = ListNode(0,head)
first = head # 用来判断是否到最后一个结点
second = dummy # 用来方便删除操作
for i in range(n): # 第一个指针先走n步后,第二个再跟上,保持n的距离
first = first.next
while first: # 一起走,第一个指针走到尽头就停止,此时第二个指针指向该删除结点的前一个指针
first = first.next
second = second.next
second.next = second.next.next # 删除结点
return dummy.next