1. 程式人生 > >【Leetcode】【連結串列】 19. Remove Nth Node From End of List / 刪除連結串列的倒數第N個節點】

【Leetcode】【連結串列】 19. Remove Nth Node From End of List / 刪除連結串列的倒數第N個節點】

Given a linked list, remove the n-th node from the end of list and return its head.

Example:

Given linked list: 1->2->3->4->5, and n = 2.

After removing the second node from the end, the linked list becomes 1->2->3->5.

Note:

Given n will always be valid.

Follow up:

Could you do this in one pass?


此題類似於求解連結串列的倒數第n個節點。分析如下



(圖示一)同樣是使用兩個指標來獲得連結串列的倒數第n個節點,但我們這個題目是要刪除倒數第n個節點,所以使用pPre指標指向欲刪除節點的前一個節點。這樣最終我們得到欲刪除節點的前一處(pPre)位置時,使 pPre->next 指向 pPre->next->next (欲刪除節點的下一個節點),即跳過欲刪除節點。 

(圖示二)注意到此題是返回刪除後的連結串列,return為連結串列的頭節點。而頭節點也可能被刪除。所以當pAhead指向為空時說明n等於連結串列長度,即欲刪除節點為頭節點,此時返回head->next即可。


之前做刪除節點時,使用的是“狸貓換太子”,將欲刪除節點的值換為後一個節點的值,再跳過後一個節點。而此題我們可以輕易得到與刪除節點的上一個節點,所以直接在上一個節點進行跳過欲刪除節點即可。

pPre指標指向欲刪除節點的前一個節點,所以在pAhead先走時,可以先走一步,這樣後面同時移動後,pPre就是倒數第n個節點的上一個節點了。

    ListNode* removeNthFromEnd(ListNode* head, int n) {
        if(head == nullptr)
            return nullptr;
        if(n<=0)                // n輸入非法
            return head;
        ListNode* pPre = head;      // 倒數第n個節點的前一個,方便進行刪除操作
        ListNode* pAhead = head;    // 先行節點
        for(int i=0; i<n; i++) {    // 正常應該少移動一位,但是這裡我們欲得到pPre為刪除節點的前一個節點
            pAhead = pAhead->next;
        }
        if(pAhead == nullptr)               // n=連結串列長度,此時刪除的是頭節點
            return head->next;
        while(pAhead->next != nullptr) {    // pPre和pAhead同時移動
            pPre = pPre->next;
            pAhead = pAhead->next;
        }
        pPre->next = pPre->next->next;        // 跳過pPre->next(要刪除的節點)
        return head;
    }