@laigary.com~/interview/coding/19-remove-nth-node-f….md$
$ cat ./coding/19-remove-nth-node-from-end-of-list.md
[Coding]·2023-01-29·4 min read

19. Remove Nth Node From End of List

19. Remove Nth Node From End of List

這一題我的第一個想法是我先走一趟算出整個 Linked List 有多長,接著我把所有的長度減去 n ,這就代表我需要從起點往下走幾步。

不過此時我們需要借助一個虛擬節點,虛擬節點的下一個點才是起點,並且從虛擬起點開始往下走,直到走到了要被刪除的點的前一個點,這時候我們就把需要刪除的節點刪掉。

# 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 not head:
            return None
        l = 0
        curr = head
        while curr:
            l += 1
            curr = curr.next
        l -= n 
        # tihs is important because sometimes the expected remove node is the head node. 
        dummy = ListNode(-1)
        dummy.next = head
        curr = dummy
        while l > 0:
            l -= 1
            curr = curr.next

        curr.next = curr.next.next    
        return dummy.next

這一題也可以用快慢指針的方式來處理

首先我們先將快指針走 n 步,如果說快指針為空了,那代表需要被刪除的節點就是一開始的起點。接著快慢指針一起走,走到快指針走完的地方,慢指針就會指向到需要被刪除的節點的前一個節點。

# 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:
        fast = head
        slow = head

        while n > 0:
            fast = fast.next
            n -= 1

        if not fast:
            return head.next

        while fast and fast.next:
            fast = fast.next
            slow = slow.next

        slow.next = slow.next.next
        return head

第三個做法

先反轉,正著做,再反轉一次。

要注意的是

  1. 如果 n == 1,要刪掉的就是最後一個節點。
  2. 反轉後,要刪掉第 n 個,我要停在第 n - 1 個,所以我的迴圈要設定在 n - 2 這個條件。
# class ListNode:
#     def __init__(self, val: int = 0, next: Optional['ListNode'] = None):
#         self.val = val
#         self.next = next

class Solution:
    def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
        # Your code goes here
        def reverse(node):
            prev = None
            while node:
                nxt = node.next
                node.next = prev
                prev = node
                node = nxt
            return prev
        
        head = reverse(head)
        if n == 1:
            head = head.next
        else:
            prev = head
            for _ in range(n - 2):
                prev = prev.next
            prev.next = prev.next.next

        return reverse(head)