【LeetCode連結串列#9】圖解:兩兩交換連結串列節點

2023-01-18 06:01:13

兩兩交換連結串列中的節點

力扣題目連結(opens new window)

給定一個連結串列,兩兩交換其中相鄰的節點,並返回交換後的連結串列。

你不能只是單純的改變節點內部的值,而是需要實際的進行節點交換。

思路

這裡還是要應用虛擬頭節點,不然交換連結串列頭節點的操作會與交換其他節點時不同

交換的過程其實不難理解,但是程式碼實現過程需要注意很多細節

下面是交換過程的圖解

首先,定義一個虛擬頭節點

並讓當前指標cur指向dummy head【注意:cur一定要在需要操作的兩個節點之前】

然後按途中順序將對應節點的next指好即可

注意:雖然畫圖我們很好理解,但是在操作過程中有很多細分步驟,如果直接上手寫程式碼會很困惑

例如,當dummy指向節點2(也就是cur.next.next)後,dummy與原來的節點1就斷開連線了

此時再想通過cur去尋找到節點1(cur.next)就行不通了,進而節點2也就無法指向節點1,步驟②無法繼續進行

與翻轉連結串列時類似,我們需要一個臨時節點temp先去儲存節點1

讓節點2通過指向temp的方式找到節點1

ps:為什麼不存節點2?因為步驟①之後節點2就已經是cur.next了,而dummy是不會變的,所以怎麼都能找到節點2

當節點2指向temp(儲存有cur.next)後,節點2與原來的節點3就斷開連線了

同理,我們應該把節點3也用臨時節點儲存,這裡用temp1儲存

於是節點2指向節點3的過程就變成了:

temp1是節點3的備份,它後面還是和節點4連著,所以不用擔心找不到節點4

至此,節點1與節點2完成了交換,cur移動到cur.next.next(即交換後此處為節點1,是什麼節點並不重要,反正待會交換的又不是當前cur指向的節點,而是後兩個節點),展開後的結果如下:

連結串列節點數為奇數時,結束條件:cur.next.next = null

連結串列節點數為偶數時,結束條件:cur.next = null

程式碼

思路通過畫圖可以很好理解,但是程式碼實現又有很多坑

class Solution {
    public ListNode swapPairs(ListNode head) {
        //定義虛擬頭節點
        ListNode dummy = new ListNode(0);
        dummy.next = head;//虛擬頭節點指向head
        ListNode cur = dummy;

        //定義臨時節點用於儲存節點1、3
        ListNode temp;
        ListNode temp1;
        

        //遍歷連結串列
        //注意這裡的結束條件,連結串列節點數為奇偶情況下是不同的
        //需要先驗證cur.next再驗證cur.next.next
        //要不然如果是偶數個節點你先驗cur.next.next直接就空指標異常了
        while(cur.next != null && cur.next.next != null ){
            //這裡下意識肯定就想開始交換了,但如果不先儲存節點就會出現空指標異常
            temp = cur.next;
            temp1 = cur.next.next.next;
            cur.next = cur.next.next;//dummy換2
            cur.next.next = temp;//2換1
            cur.next.next.next = temp1;//1換3
            cur = cur.next.next;//移動cur至新的待交換的兩個節點前

        }
        //遍歷結束,返回dummy的下一個節點即可
        return dummy.next;
    }
}

易錯點:
1、建立完dummy後記得指向head

2、交換過程中要以cur為參照點來表示參與交換的節點,不要變,例如1換3時不能寫成

`temp.next = temp1;