Reverse Linked List (反轉鏈結串列) 🟢 Easy¶
📌 LeetCode #206 — 題目連結 | NeetCode 解說
1. 🧐 Problem Dissection (釐清問題)¶
題目給一個 singly linked list 的 head。 請反轉這個 List,並回傳新的 head。
- Input:
head = [1,2,3,4,5] - Output:
[5,4,3,2,1] - Constraints:
- number of nodes: \(0 \dots 5000\).
-5000 <= Node.val <= 5000.
2. 🐢 Brute Force Approach (暴力解)¶
用一個 Stack 把所有 node values 存起來,然後重建一個新的 List。
- Time: \(O(n)\)。
- Space: \(O(n)\)。
- Result: 雖然可行,但面試官通常期望 \(O(1)\) Space。
3. 💡 The "Aha!" Moment (優化)¶
我們可以用 Iterative 的方式原地 (In-place) 反轉。
我們只需要維護三個指標:
prev: 指向「前一個」節點 (反轉後的下一個)。初始為nullptr。curr: 指向「當前」節點。初始為head。next: 用來暫存curr->next,因為我們會切斷這個連結。
步驟: 當 curr 不為空時:
next = curr->next(暫存下一步)curr->next = prev(反轉箭頭!指向前一個人)prev = curr(推進 prev)curr = next(推進 curr)
當迴圈結束時,curr 是 nullptr,而 prev 會停在原本的最後一個節點(也就是新的 Head)。回傳 prev。
Recursive Approach (Optional): 遞迴解法雖然優雅,但空間複雜度是 \(O(n)\) (Stack depth)。Iterative 是最佳解。
🎬 Visualization (演算法視覺化)¶
4. 💻 Implementation (程式碼)¶
Approach: Iterative (O(1) Space)¶
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* reverseList(ListNode* head) {
ListNode* prev = nullptr;
ListNode* curr = head;
while (curr != nullptr) {
// 1. Save next
ListNode* nextTemp = curr->next;
// 2. Reverse link
curr->next = prev;
// 3. Move pointers
prev = curr;
curr = nextTemp;
}
return prev;
}
};
Approach: Recursive (O(n) Space)¶
class Solution {
public:
ListNode* reverseList(ListNode* head) {
// Base case: empty or single node
if (head == nullptr || head->next == nullptr) {
return head;
}
// Recursive step
ListNode* newHead = reverseList(head->next);
// Reverse the link
head->next->next = head; // 讓下一個節點指向自己
head->next = nullptr; // 斷開自己原本的指向
return newHead;
}
};
Python Reference¶
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
prev, curr = None, head
while curr:
nxt = curr.next
curr.next = prev
prev = curr
curr = nxt
return prev
5. 📝 Detailed Code Comments (詳細註解)¶
class Solution {
public:
ListNode* reverseList(ListNode* head) {
// prev 會變成新的 tail (指向 nullptr)
ListNode* prev = nullptr;
ListNode* curr = head;
while (curr != nullptr) {
// 暫存下一個節點,因為我們等一下會切斷 curr->next
ListNode* nextNode = curr->next;
// 關鍵動作:將當前節點的指針「回頭」指
curr->next = prev;
// 往下一個節點推進
// prev 跑到現在的位置
prev = curr;
// curr 跑到剛剛暫存的位置
curr = nextNode;
}
// 當 curr 為 null 時,loop 結束,此時 prev 指向原本的最後一個節點
// 也就是新的 head
return prev;
}
};
6. 📊 Rigorous Complexity Analysis (複雜度分析)¶
- Time Complexity: \(O(n)\)
- 遍歷每個節點一次。
- Space Complexity: \(O(1)\)
- 只使用了
prev,curr,next三個指標,沒有額外的資料結構。
7. 💼 Interview Tips (面試技巧) ⭐ 高頻題¶
🎯 Follow-up 問題¶
面試官可能會問的延伸問題:
- 遞迴版本?
- K 個一組反轉?
🚩 常見錯誤 (Red Flags)¶
避免這些會讓面試官扣分的錯誤:
- ⚠️ 沒有保存 next 指標
- ⚠️ 忘記返回新頭節點
✨ 加分項 (Bonus Points)¶
這些會讓你脫穎而出:
- 💎 迭代和遞迴兩種解法
- 💎 清晰的指標操作解釋
📚 Related Problems (相關題目)¶
站內相關¶
進階挑戰¶
- Reverse Linked List Ii — LeetCode