程式碼隨想錄第4天 | 24. 兩兩交換連結串列中的節點、19.刪除連結串列的倒數第N個節點、面試題 02.07. 連結串列相交、142.環形連結串列II

跳圈發表於2024-06-08

題目:24.兩兩交換連結串列中的節點

思路:

設定虛擬頭結點,雙指標+臨時指標,(感覺也能遞迴,未嘗試)
時間複雜度:O(n)
空間複雜度:O(1)

坑:

1.又忘了 else{}和return
2.試圖訪問空指標,多個條件的順序問題及"&&""||"問題,cur->next要寫在cur->next->next前面

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        if (head == nullptr)
            return head;
        else {
            ListNode* dummyhead = new ListNode(0);
            dummyhead->next = head;
            ListNode* cur = dummyhead;
            ListNode* post = head;
            ListNode* pre = new ListNode(0);
            ListNode* tmp;
            while (cur->next!=nullptr&&cur->next->next!=nullptr) {  //最佳化後,報錯,
            /*1. 是“&&”不是“||”, 或的話,若cur->next為nullptr,則cur->next->next就訪問空指標了,
              2.cur->next要寫在cur->next->next前面,理由同上
            */
                pre = post->next;
                tmp = pre->next;
                cur->next = pre;
                pre->next = post;
                post->next=tmp; //提交heap-use-after-free報錯了,我的連結串列交換後,這裡斷了,
                cur = post;
                post = tmp;
            }
            return dummyhead->next;
        }
    }
};
/*未最佳化版本
            while (post!=nullptr) {  //可最佳化,迴圈結束條件不對,看迴圈體結束部分來思考
                pre = post->next;
                if(pre==nullptr){  //缺少判斷條件 長度為奇數的連結串列 這部分可最佳化
                    return dummyhead->next;
                }
                tmp = pre->next;
                cur->next = pre;
                pre->next = post;
                post->next=tmp; //提交heap-use-after-free報錯了,我的連結串列交換後,這裡斷了,
                cur = post;
                post = tmp;
            }
*/

補充:

1.heap-use-after-free on address
尾節點如果沒有rear->next=NULL;這個連結串列就會錯呢? 尾節點沒有明確指向,連結串列不完整,計算機認為連結串列未結束
2.懸掛指標(Dangling Pointer)。如果我們試圖訪問已經被釋放的記憶體,就會觸發"heap-use-after-free"錯誤。

題目:19.刪除連結串列的倒數第N個節點

思路:

1.遍歷連結串列獲取連結串列長度,然後刪除結點,釋放被刪除節點
2.進階要求是,使用一趟掃描實現-->隨想錄思路 啊 是快慢指標,快指標先走N+1步,
時間複雜度: O(n)
空間複雜度: O(1)

坑:

試圖訪問空指標,主要在cur->next時,cur可能為空指標

/** Definition for singly-linked list.同上*/
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* dummyHead=new ListNode(0);
        dummyHead->next=head;
        ListNode* fast=dummyHead;  //fast和slow初始指向虛擬head不是head
        ListNode* slow=dummyHead;
        ListNode* tmp;
        n++; //刪除結點,slow要指向被刪除結點的前一個節點,所以fast要多走一步,slow和fast相差n+1步
        while(n--&&fast!=nullptr){    //錯誤,需要判斷fast是否為空,
            fast=fast->next;     
        }
        while(fast!=nullptr){  //錯誤,試圖訪問空指標 fast不為空 不用->next
            fast=fast->next;
            slow=slow->next;
        }
        tmp=slow->next;
        slow->next=slow->next->next;
        delete tmp;
        return dummyHead->next;
    }
};

補充:

個人對快慢雙指標還是沒有理解到位
雙指標解題:
1.指標相鄰:刪除某個結點,或交換兩個結點
2.指標不相鄰,快滿指標間隔N步

題目:面試題02.07.連結串列相交

思路:

1.兩個這指標分別指向a,b,兩層迴圈遍歷,比較->next是否相等,有點繁瑣
2.看了leetcode的引導式提示:從兩連結串列長度相同時相交到不同長度,一個先走差值步,使得二者相同才判斷;
時間複雜度:O(n + m)
空間複雜度:O(1)

坑:

  1. 當兩連結串列長度相同時,兩連結串列不相交可以和相交放一起判斷
  2. 使用pa->next判空,則少算了最後一個pa節點
  3. 沒比較兩連結串列長度,就預設進行下去了;
/** Definition for singly-linked list.同上*/
class Solution {
public:
    ListNode* getIntersectionNode(ListNode* headA, ListNode* headB) {
        ListNode* pA = headA;
        ListNode* pB = headB;

        int m = 0, n = 0, diff = 0; // diff表示兩連結串列的差值 (用英語gap也行)
        pA = headA;                 // 指標返回頭結點
        pB = headB;
        while (pA != nullptr) { // 錯誤,pa->next判空,則少算了最後一個pa節點
            pA = pA->next;
            m++;
        }
        while (pB != nullptr) {
            pB = pB->next;
            n++;
        }
        pA = headA;
        pB = headB;
        // 錯誤,m和n的大小沒有判斷,
        if (m < n) { // 交換使得,pA和m表示較長的連結串列
            swap(pA, pB);
            swap(m, n);
        }
        diff = m - n;
        while (diff--) {
            pA = pA->next;
        }
        while (pA!=nullptr) {
            if(pA==pB)
                return pA;
            pA = pA->next;
            pB = pB->next;
        }
        return NULL;
    }
};

題目:142.環形連結串列Ⅱ

思路:

坑:

補充:

今日總結

連結串列類的題主要還是看思路,想得到關鍵,就後面很順利

相關文章