1. 程式人生 > 其它 >92. 反轉連結串列 II(C++)

92. 反轉連結串列 II(C++)

目錄

題目

給你單鏈表的頭指標 head 和兩個整數 leftright ,其中 left <= right 。請你反轉從位置 left 到位置 right 的連結串列節點,返回 反轉後的連結串列 。

示例 1:

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

示例 2:

輸入:head = [5], left = 1, right = 1
輸出:[5]

提示:

  • 連結串列中節點數目為 n
  • 1 <= n <= 500
  • -500 <= Node.val <= 500

題解

對於連結串列的問題,一般都是要建一個 dummy node

連上原連結串列的頭結點,以此來規範頭節點變動和其他節點變動的程式碼,進行格式統一。

以題目中的例子來說,變換的是 2,3,4 這三個點,我們需要找到第一個開始變換結點的前一個結點,只要讓 pre 向後走 m-1 步即可,用 pre 指向它。由於一次只能交換兩個結點,所以我們按如下的交換順序:

1 -> 2 -> 3 -> 4 -> 5 -> NULL
1 -> 3 -> 2 -> 4 -> 5 -> NULL // 第一次變換將結點 3 放到結點 1 的後面
1 -> 4 -> 3 -> 2 -> 5 -> NULL // 第二次變換將結點 4 放到結點 1 的後面

可以看出來,總共需要 right-left步即可,因為每次變換都是規律的操作,就以第一次變換進行舉例。剛開始,pre 指向結點 1,cur 指向結點 2,然後我們建立一個臨時的結點 tmp用臨時變數儲存某個結點就是為了首先斷開該結點和前面結點之間的聯絡,這可以當作一個規律記下來。

每一次節點交換分為以下三個步驟:

  • 第一步斷開結點 2 和結點 3,將結點 2 的 next 連到結點 4 上:

    cur->next = t->next
    
  • 第二步將結點 3 連到結點2的前面,即

    t->next = pre->next
    
  • 第三步將結點 1 連到結點 3,即

    pre->next = tmp
    

這裡跟常見的連結串列反轉最大的區別在於以前prev、cur會向隨著連結串列遍歷反轉逐漸向後移動,這裡的prev、cur其實指向並沒有改變。即這裡的prev一直是1, cur一直是2, 是cur->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* reverseBetween(ListNode* head, int left, int right) {
        // 設定頭節點,來規範化頭節點反轉的特殊情況
        ListNode* dummy = new ListNode(-1);
        dummy->next = head;
        ListNode* pre = dummy;
        // left-1是為了找到開始變換節點的前一節點
        for (int i = 0; i < left - 1; i++) 
            pre = pre->next;
        // 本題中pre和cur不會變動!!
        ListNode* cur = pre->next;
        for (int i = left ; i < right; i++) {
            ListNode* tmp = cur->next;
             // 首先斷開臨時節點和前面節點的關係
            cur->next = tmp->next;
            tmp->next = pre->next;
            pre->next = tmp;
        }
        return dummy->next;
    }
};