LeetCode刷題系列19

給定一個鏈表,刪除鏈表的倒數第 n 個節點,並且返回鏈表的頭結點。

示例:

給定一個鏈表: 1->2->3->4->5, 和 n = 2.

當刪除了倒數第二個節點後,鏈表變爲 1->2->3->5.

說明:

給定的 n 保證是有效的。

進階:

你能嘗試使用一趟掃描實現嗎?

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。
  • C++編程實現:

(1)方法一:

兩次遍歷算法

思路

我們注意到這個問題可以容易地簡化成另一個問題:刪除從列表開頭數起的第(L - n + 1)個結點,其中L是列表的長度。
只要我們找到列表的長度L,這個問題就很容易解決。

算法

首先我們將添加一個啞結點作爲輔助,該結點位於列表頭部。啞結點用來簡化某些極端情況,例如列表中只含有一個結點,
或需要刪除列表的頭部。在第一次遍歷中,我們找出列表的長度L。然後設置一個指向啞結點的指針,並移動它遍歷列表,
直至它到達第(L−n)個結點那裏。我們把第(L−n)個結點的 next 指針重新鏈接至第 (L−n+2) 個結點,完成這個算法。

作者:LeetCode
鏈接:https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/solution/shan-chu-lian-biao-de-dao-shu-di-nge-jie-dian-by-l/
來源:力扣(LeetCode)
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* dummy = new ListNode(0);
        dummy->next = head;
        int nlength = 0;
        ListNode* first = head;
        while(first)
        {
            nlength++;
            first = first->next;
        }
        nlength -= n;
        first = dummy;
        while(nlength>0)
        {
            nlength--;
            first = first->next;
        }
        first->next = first->next->next;
        return dummy->next;
    }
};

複雜度分析:

    時間複雜度:O(L),該算法對列表進行了兩次遍歷,首先計算了列表的長度L其次找到第(L−n)個結點。 操作執行了2L−n步,時間複雜度爲O(L)。

    空間複雜度:O(1),我們只用了常量級的額外空間。

 

(2)方法二:

算法

上述算法可以優化爲只使用一次遍歷。我們可以使用兩個指針而不是一個指針。第一個指針從列表的開頭向前移動 n-1步後,
判斷結點next是否到達末尾,如果到達末尾則需要刪除的是第一個元素,直接返回head->next就行了;如果結點next沒有
到達末尾,第二個指針將從列表的開頭出發。現在,這兩個指針被n個結點分開。我們通過同時移動兩個指針向前來保持這
個恆定的間隔,直到第一個指針到達最後一個結點。此時第二個指針將指向從最後一個結點數起的第n個結點。我們重新鏈
接第二個指針所引用的結點的 next 指針指向該結點的下下個結點。

作者:LeetCode
鏈接:https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/solution/shan-chu-lian-biao-de-dao-shu-di-nge-jie-dian-by-l/
來源:力扣(LeetCode)
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* forward = head;
        ListNode* backward = head;
        for (int i=0; i<n-1; i++)
            forward = forward->next;
        if (forward->next == NULL)
            return head->next;
        forward = forward->next;
        while(forward->next)
        {
            forward = forward->next;
            backward = backward->next;
        }
        backward->next = backward->next->next;
        return head;
    }
};

複雜度分析

    時間複雜度:O(L),該算法對含有L個結點的列表進行了一次遍歷。因此時間複雜度爲O(L)。

    空間複雜度:O(1),我們只用了常量級的額外空間。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章