Given the head
of a linked list, remove the nth
node from the end of the list and return its head.
Example 1:
Input: head = [1,2,3,4,5], n = 2 Output: [1,2,3,5]
Example 2:
Input: head = [1], n = 1 Output: []
Example 3:
Input: head = [1,2], n = 1 Output: [1]
Constraints:
- The number of nodes in the list is
sz
. 1 <= sz <= 30
0 <= Node.val <= 100
1 <= n <= sz
Follow up: Could you do this in one pass?
题目大意:给定一个链表,要求删掉倒数第n个节点,题目给出的限制条件是,保证链表不为空,n大于等于1且小于等于节点总数,即要删除的倒数第n个节点一定存在,这样我们在解答时就不用做边界判断。
解题思路:最直观的解法是先遍历一遍链表算出节点总个数m,那么要删的倒数第n个节点就是正数第(m - n + 1)个节点;然后再重头开始遍历链表找到第(m-n+1)个节点将其删掉。这种解法需要遍历两遍链表。而题目进一步问能否只遍历一遍,这就需要用两个指针来解决,定义两个指针p1, p2都指向链表头节点的前一个节点(可以定义一个头结点的头节点即preHead.next=head,这么处理是为了把head也当成一个普通节点而不需要特殊处理),让p1先往前走n步,然后p2启动跟p1一起同步往前走,当p1走到最后一个节点时(相当于p1又走了n-m步),那么p2指向的节点就是要删除节点的前一个节点(正数第n-m个节点),p2.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: Optional[ListNode], n: int) -> Optional[ListNode]:
preHead = ListNode(0, head)
p1,p2 = preHead, preHead
for i in range(n):
p1 = p1.next
while p1.next:
p1 = p1.next
p2 = p2.next
p2.next = p2.next.next
return preHead.next