鏈表反轉(鏈表 + 迭代 / 遞歸)
題目描述:給你單鏈表的頭節點 head,請你反轉鏈表,并返回反轉后的鏈表頭節點。
示例:輸入鏈表 1→2→3→4→5 → 輸出 5→4→3→2→1。
思路提示:
迭代法:用三個指針 prev(前一個節點,初始 nullptr)、curr(當前節點,初始 head)、next(臨時存儲下一個節點),遍歷鏈表時依次修改 curr->next = prev,再更新三個指針。
遞歸法:遞歸反轉 head 的下一個節點,再將 head 接到反轉后的鏈表尾部,時間復雜度 O (n),空間復雜度 O (n)(遞歸棧)。
#include <iostream>using namespace std;// ---------- 1. 節點定義 ----------
struct ListNode {int val;ListNode* next;ListNode(int v = 0, ListNode* n = nullptr) : val(v), next(n) {}
};// ---------- 2. 迭代法 ----------
ListNode* reverseList_iter(ListNode* head) {ListNode* prev = nullptr; // 新鏈表的頭ListNode* curr = head; // 正在處理的節點while (curr) {ListNode* nextTmp = curr->next; // 臨時保存下一個curr->next = prev; // 反向prev = curr; // prev 前進一步curr = nextTmp; // curr 前進一步}return prev; // prev 變成新頭節點
}// ---------- 3. 遞歸法 ----------
ListNode* reverseList_recur(ListNode* head) {if (!head || !head->next) return head; // 空或最后一個節點ListNode* newHead = reverseList_recur(head->next); // 先反轉后面的鏈表head->next->next = head; // 把當前節點接到已反轉部分的尾巴head->next = nullptr; // 防止成環return newHead;
}// ---------- 4. 輔助:打印鏈表 ----------
void printList(ListNode* head) {for (ListNode* p = head; p; p = p->next)cout << p->val << (p->next ? "→" : "");cout << endl;
}// ---------- 5. 測試 ----------
int main() {// 構造 1→2→3→4→5ListNode* head = new ListNode(1);head->next = new ListNode(2);head->next->next = new ListNode(3);head->next->next->next = new ListNode(4);head->next->next->next->next = new ListNode(5);cout << "Original: "; printList(head);// 迭代版ListNode* newHead_iter = reverseList_iter(head);cout << "Reversed (iter): "; printList(newHead_iter);// 遞歸版(再反轉回來演示)ListNode* newHead_recur = reverseList_recur(newHead_iter);cout << "Re-reversed (recur): "; printList(newHead_recur);return 0;
}
拆解 1:構造函數的參數與默認值
構造函數 ListNode(int v = 0, ListNode* n = nullptr) 有兩個參數:
int v:用于初始化 val(節點數據),默認值為 0
ListNode* n:用于初始化 next(下一個節點指針),默認值為 nullptr(空指針)
默認參數的作用:調用構造函數時,可以不傳參數、傳 1 個參數或傳 2 個參數,非常靈活。
拆解 2:初始化列表 : val(v), next(n)
這是 C++ 的初始化列表語法,作用是在構造函數體執行前,直接初始化成員變量:
val(v):將成員變量 val 初始化為參數 v 的值
next(n):將成員變量 next 初始化為參數 n 的值
相比在構造函數體內賦值(如 val = v;),初始化列表更高效,尤其適合 const 成員或自定義類型成員的初始化。