題目描述:html
給定一個鏈表,刪除鏈表的倒數第 n 個節點,而且返回鏈表的頭結點。算法
示例:優化
給定一個鏈表: 1->2->3->4->5, 和 n = 2. 當刪除了倒數第二個節點後,鏈表變爲 1->2->3->5.
說明:spa
給定的 n 保證是有效的。指針
解題思路:code
思路htm
咱們注意到這個問題能夠容易地簡化成另外一個問題:刪除從列表開頭數起的第 (L - n + 1)(L−n+1) 個結點,其中 LL 是列表的長度。只要咱們找到列表的長度 LL,這個問題就很容易解決。blog
算法rem
首先咱們將添加一個啞結點做爲輔助,該結點位於列表頭部。啞結點用來簡化某些極端狀況,例如列表中只含有一個結點,或須要刪除列表的頭部。在第一次遍歷中,咱們找出列表的長度 LL。而後設置一個指向啞結點的指針,並移動它遍歷列表,直至它到達第 (L - n)(L−n) 個結點那裏。咱們把第 (L - n)(L−n) 個結點的 next
指針從新連接至第 (L - n + 2)(L−n+2) 個結點,完成這個算法。io
算法
上述算法能夠優化爲只使用一次遍歷。咱們能夠使用兩個指針而不是一個指針。第一個指針從列表的開頭向前移動 n+1n+1 步,而第二個指針將從列表的開頭出發。如今,這兩個指針被 nn 個結點分開。咱們經過同時移動兩個指針向前來保持這個恆定的間隔,直到第一個指針到達最後一個結點。此時第二個指針將指向從最後一個結點數起的第 nn個結點。咱們從新連接第二個指針所引用的結點的 next
指針指向該結點的下下個結點。
class Solution: def removeNthFromEnd(self, head, n): """ :type head: ListNode :type n: int :rtype: ListNode """ h = ListNode(-1) h.next = head p, q = h, h for _ in range(n + 1): q = q.next while q != None: p = p.next q = q.next p.next = p.next.next return h.next