1. 程式人生 > 其它 >移除單鏈表中指定位置的節點

移除單鏈表中指定位置的節點

題目描述

給定一個連結串列,刪除連結串列的倒數第 nn 個節點,並且返回連結串列的頭結點。

示例1

輸入:head = [1,2,3,4,5], n = 2
輸出:[1,2,3,5]

輸入:head[1], n=1
輸出:[]

輸入:head = [1,2], n = 1
輸出:[1]

進階要求

嘗試用一趟掃描實現

演算法1

兩次遍歷
  1. 第一次遍歷求出連結串列長度
  2. 第二次遍歷刪掉指定的結點
  3. 注意刪掉頭結點的特殊情況(這個自己沒有考慮到,當提交調錯的時候才解決掉這個問題)
時間複雜度

遍歷兩次連結串列,空間複雜度為O(L)

空間複雜度

僅需要定義常數個指標變數,故時間複雜度為O(1)

程式碼
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        int sum = 0;
        ListNode* a = head;

        // 求一下連結串列的長度
        while (a) {
            ++sum;
            a = a->next;
        }
        
        // 判斷刪掉第一個節點的特殊情況
        if (sum == n) {
            head = head->next;
            return head;
        }

        ListNode* b = head;

        // 遍歷刪掉指定的節點
        for (int i = 0; i < sum - n - 1; i++) {
            head = head->next;
        }
        head->next = head->next->next;

        return b;
    }
};

演算法2

一次遍歷

1.在頭部之前新增保護點
2.設定兩個指標first和second,均指向保護節點
3.first指標先向後移動n + 1個結點
4.然後first和second指標同時向後移動,直到first指標指向空,此時second結點指向的下一個結點需要刪除

原理

始終保持兩個指標之間間隔n個結點,在first到達終點時,second的下一個結點就是從結尾數第n個結點。

時間複雜度

遍歷兩次連結串列,空間複雜度為O(L)

空間複雜度

僅需要定義常數個指標變數,故時間複雜度為O(1)

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* e_head = new ListNode(0);
        e_head->next = head;                                            

        ListNode* first = e_head;
        ListNode* second = e_head;

        n++;
        while (n--) {
            first = first->next;
        }

        while (first) {
            first = first->next;
            second = second->next;
        }
        second->next = second->next->next;

        return e_head->next;
    }
};