一、題目是啥?一句話說清
給你一個鏈表和兩個整數 left 和 right,反轉從第 left 個節點到第 right 個節點的子鏈表,并返回反轉后的鏈表。其他部分保持不變。
示例:
- 輸入:head = [1,2,3,4,5], left = 2, right = 4
- 輸出:[1,4,3,2,5](反轉了從第2到第4個節點)
二、解題核心
使用啞節點簡化操作,找到要反轉子鏈表的前一個節點,斷開子鏈表,反轉它,然后重新連接回原鏈表。 這就像把鏈表的一段剪下來,反轉后再縫回去。
三、關鍵在哪里?(3個核心點)
想理解并解決這道題,必須抓住以下三個關鍵點:
1. 啞節點(Dummy Node)的使用
- 是什么:在鏈表頭部添加一個啞節點,其 next 指向頭節點。
- 為什么重要:當 left 為 1 時,頭節點會被反轉,啞節點可以避免處理頭節點變化的特殊情況,使代碼更統一。
2. 找到關鍵節點
- 是什么:找到要反轉子鏈表的前一個節點(pre)、子鏈表的開始節點(start)和結束節點(end)。
- 為什么重要:只有準確找到這些節點,才能正確斷開和連接子鏈表。
3. 反轉子鏈表并重新連接
- 是什么:斷開子鏈表后,反轉它,然后將反轉后的子鏈表頭連接到 pre 的 next,將反轉后的子鏈表尾連接到原鏈表的后續節點。
- 為什么重要:如果連接錯誤,鏈表會斷開或形成環。
四、看圖理解流程(通俗理解版本)
讓我們用鏈表 1 → 2 → 3 → 4 → 5 和 left=2, right=4 的例子來可視化過程:
-
初始化:
- 創建啞節點 dummy,其 next 指向頭節點 1。
- 初始狀態:dummy → 1 → 2 → 3 → 4 → 5
-
找到 pre 節點:
- pre 節點是反轉部分的前一個節點,即第 left-1 個節點。這里 left=2,所以 pre 是第 1 個節點,即節點 1。
- 從 dummy 移動 left-1=1 步,pre 指向節點 1。
-
找到 start 和 end 節點:
- start 節點是 pre 的 next,即節點 2。
- end 節點是反轉部分的最后一個節點,從 start 移動 right-left=2 步,即節點 4。
-
斷開子鏈表:
- 記錄 end 的下一個節點 succ,即節點 5。
- 將 end 的 next 設為 null,斷開子鏈表:子鏈表為 2 → 3 → 4 → null
-
反轉子鏈表:
- 反轉子鏈表:4 → 3 → 2 → null
- 反轉后的頭節點是 4,尾節點是 2。
-
重新連接:
- 將 pre 的 next(即節點 1 的 next)指向反轉后的頭節點 4。
- 將反轉后的尾節點 2 的 next 指向 succ(節點 5)。
- 最終鏈表:dummy → 1 → 4 → 3 → 2 → 5
-
返回結果:返回 dummy.next,即節點 1。
五、C++ 代碼實現(附詳細注釋)
#include <iostream>
using namespace std;// 鏈表節點定義
struct ListNode {int val;ListNode *next;ListNode() : val(0), next(nullptr