2022-10-14 算法訓練第三天(203.移除鏈表元素 707.設(shè)計鏈表 206.反轉(zhuǎn)鏈表 )

203.移除鏈表元素

解題思路:

  1. 為鏈表新增一個虛擬頭節(jié)點,定義一個當前指針指向虛擬頭節(jié)點。通過while循環(huán)遍歷鏈表,只有當前指針指向最后一個節(jié)點的時候,循環(huán)停止。
  2. 每次循環(huán)中,首先判斷當前指針指向的節(jié)點的下一個節(jié)點的元素是否為目標值,如果為真,定義一個臨時變量指向即將刪除的下一個節(jié)點,然后將即將刪除的節(jié)點中next信息傳遞給當前節(jié)點的next,delete改臨時指針,釋放下一個節(jié)點的空間。
  3. 如果為否,當前指針指向下一個節(jié)點。當前指針指向節(jié)點的next為空之后,說明當前指針已經(jīng)指向了最后一個指針,循環(huán)結(jié)束。
  4. 最后將虛擬頭節(jié)點中的next賦值給head頭指針,最后釋放虛擬頭節(jié)點的空間。
        ListNode* dummyHead = new ListNode(0); 
        dummyHead->next = head; 
        ListNode* cur = dummyHead;
        while (cur->next != NULL) {
            if(cur->next->val == val) {
                ListNode* tmp = cur->next;
                cur->next = cur->next->next;
                delete tmp;
            } else {
                cur = cur->next;
            }
        }
        head = dummyHead->next;
        delete dummyHead;
        return head;

707.設(shè)計鏈表

解題思路;

  1. 設(shè)計一個鏈表類,一個完整的鏈表必須要包含頭指針,所以為增添一個私有數(shù)據(jù)成員為指向鏈表頭結(jié)點的指針,指針類型為一個節(jié)點類型,所以要在類中明確節(jié)點的結(jié)構(gòu),定義了一個結(jié)構(gòu)體,結(jié)構(gòu)體中的構(gòu)造函數(shù)用于初始化結(jié)構(gòu)體,不加構(gòu)造函數(shù)就沒辦法在括號中為節(jié)點初始化,只能借助于->和.來對節(jié)點中的元素進行初始化。私有成員還包含了size變量,用于判斷索引值是否合法。
  2. 鏈表類的構(gòu)造函數(shù)中,開辟一個節(jié)點空間,同時初始化頭指針,但該節(jié)點為虛擬頭節(jié)點。另一方面size初始化為0;
  3. get函數(shù)實現(xiàn)過程,首先要判斷索引是否合法。定義臨時指針指向真實頭節(jié)點,這一點很關(guān)鍵。后接while循環(huán)開始移動當前指針,指針先移動,索引在移動,索引會移動index位,指針也移動index位,最終當前指針指向目標節(jié)點,直接取值。
class MyLinkedList {
public:
    // 定義鏈表節(jié)點結(jié)構(gòu)體
    struct LinkedNode {
        int val;
        LinkedNode* next;
        LinkedNode(int val):val(val), next(nullptr){}
    };

    // 初始化鏈表
    MyLinkedList() {
        _dummyHead = new LinkedNode(0); // 這里定義的頭結(jié)點 是一個虛擬頭結(jié)點,而不是真正的鏈表頭結(jié)點
        _size = 0;
    }

    // 獲取到第index個節(jié)點數(shù)值,如果index是非法數(shù)值直接返回-1, 注意index是從0開始的,第0個節(jié)點就是頭結(jié)點
    int get(int index) {
        if (index > (_size - 1) || index < 0) {
            return -1;
        }
        LinkedNode* cur = _dummyHead->next;
        while(index--){ // 如果--index 就會陷入死循環(huán)
            cur = cur->next;
        }
        return cur->val;
    }

    // 在鏈表最前面插入一個節(jié)點,插入完成后,新插入的節(jié)點為鏈表的新的頭結(jié)點
    void addAtHead(int val) {
        LinkedNode* newNode = new LinkedNode(val);
        newNode->next = _dummyHead->next;
        _dummyHead->next = newNode;
        _size++;
    }

    // 在鏈表最后面添加一個節(jié)點
    void addAtTail(int val) {
        LinkedNode* newNode = new LinkedNode(val);
        LinkedNode* cur = _dummyHead;
        while(cur->next != nullptr){
            cur = cur->next;
        }
        cur->next = newNode;
        _size++;
    }

    // 在第index個節(jié)點之前插入一個新節(jié)點,例如index為0,那么新插入的節(jié)點為鏈表的新頭節(jié)點。
    // 如果index 等于鏈表的長度,則說明是新插入的節(jié)點為鏈表的尾結(jié)點
    // 如果index大于鏈表的長度,則返回空
    void addAtIndex(int index, int val) {
        if (index > _size) {
            return;
        }
        LinkedNode* newNode = new LinkedNode(val);
        LinkedNode* cur = _dummyHead;
        while(index--) {
            cur = cur->next;
        }
        newNode->next = cur->next;
        cur->next = newNode;
        _size++;
    }

    // 刪除第index個節(jié)點,如果index 大于等于鏈表的長度,直接return,注意index是從0開始的
    void deleteAtIndex(int index) {
        if (index >= _size || index < 0) {
            return;
        }
        LinkedNode* cur = _dummyHead;
        while(index--) {
            cur = cur ->next;
        }
        LinkedNode* tmp = cur->next;
        cur->next = cur->next->next;
        delete tmp;
        _size--;
    }

    // 打印鏈表
    void printLinkedList() {
        LinkedNode* cur = _dummyHead;
        while (cur->next != nullptr) {
            cout << cur->next->val << " ";
            cur = cur->next;
        }
        cout << endl;
    }
private:
    int _size;
    LinkedNode* _dummyHead;

};

206.反轉(zhuǎn)鏈表

解題思路:

雙指針法:定義三個指針,一個當前指針,由于沒有虛擬節(jié)點,它直接指向頭節(jié)點。一個臨時指針用于保存之后節(jié)點的信息。一個pre指針用于指向前一個節(jié)點。
首先保存下一個節(jié)點的位置,將當前節(jié)點指向前一個節(jié)點,pre節(jié)點指向當前節(jié)點,當前指針指向下一個節(jié)點。

class Solution {
public: 
    ListNode* reverseList(ListNode* head) {
        ListNode* temp; // 保存cur的下一個節(jié)點
        ListNode* cur = head;
        ListNode* pre = NULL;
        while(cur) {
            temp = cur->next;  // 保存一下 cur的下一個節(jié)點,因為接下來要改變cur->next
            cur->next = pre; // 翻轉(zhuǎn)操作
            // 更新pre 和 cur指針
            pre = cur;
            cur = temp;
        }
        return pre;
    }
};

遞歸法

class Solution {
public:
    ListNode* reverse(ListNode* pre,ListNode* cur){
        if(cur == NULL) return pre;
        ListNode* temp = cur->next;
        cur->next = pre;
        // 可以和雙指針法的代碼進行對比,如下遞歸的寫法,其實就是做了這兩步
        // pre = cur;
        // cur = temp;
        return reverse(cur,temp);
    }
    ListNode* reverseList(ListNode* head) {
        // 和雙指針法初始化是一樣的邏輯
        // ListNode* cur = head;
        // ListNode* pre = NULL;
        return reverse(NULL, head);
    }

};
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容