給定單鏈表 head → 1 → 2 → 3 → NULL,反轉為 head → 3 → 2 → 1 → NULL。三種經典思路:
遍歷鏈表存入 Node* arr[N],再按 arr[N-1] → arr[N-2] → ... → arr[0] 重鏈。缺點:額外 O(N) 空間,兩次遍歷,破壞原結構局部性。
使用 p(已反轉部分尾部)、q(待處理節點)、r(剩餘鏈表)三指標協作:
Node* ReverseList(Node* head) {
if (!head || !head->next) return head;
Node *p = head, *q = head->next, *r;
head->next = nullptr; // 原頭節點變尾,next 置空
while (q) {
r = q->next; // 1. 保存剩餘鏈表
q->next = p; // 2. 反轉指向
p = q; // 3. p 前進
q = r; // 4. q 前進
}
return p; // p 為新頭節點
}
圖解關鍵步驟:
p→1、q→2、1→NULLr→3、q→2→1、p→2、q→3r→NULL、q→3→2→1、p→3、q→NULLp (3)思路:保持 head 不動,將第 2 個節點開始的每個節點,依次「摘下」插入到 head 之後。最終 head 後面是逆序鏈表,最後將 head 移至新表尾。
Node* ReverseList3(Node* head) {
if (!head || !head->next) return head;
Node *p = head->next, *q;
while (p->next) {
q = p->next; // 待插入節點
p->next = q->next; // p 跳過 q
q->next = head->next; // q 插入 head 後
head->next = q;
}
// 最後處理 head:成環 → 斷環 → 移動 head
p->next = head;
head = p->next->next;
p->next->next = nullptr;
return head;
}
圖解精髓:
head→1→2→3→NULLhead→2→1→3→NULLhead→3→2→1→NULL#include <iostream>
using namespace std;
struct Node { int val; Node* next; };
Node* Create() { /* 互動式建立鏈表 */ }
void Display(Node* head) { /* 遍歷輸出 */ }
Node* ReverseList2(Node* head) { /* 三指標法 */ }
Node* ReverseList3(Node* head) { /* 頭插法 */ }
int main() {
Display(ReverseList3(Create()));
return 0;
}
| 方法 | 空間複雜度 | 時間複雜度 | 特點 |
|---|---|---|---|
| 陣列法 | O(N) | O(N) | 簡單直觀,適合教學 |
| 三指標法 | O(1) | O(N) | 標準原地算法,面試必會 |
| 頭插法 | O(1) | O(N) | 思路新穎,利用哨兵節點 |
掌握三指標迭代法是核心,理解頭插法能拓寬思維,兩者都是單鏈表指針操作功力的試金石。