🎯 什麼情境該想到我
當你在準備/進行技術面試的程式題,想把「解題過程」表現好(而不只是湊出答案)時。
⚙️ 怎麼用(拿到題別急著寫)
- 先釐清思路:畫圖(形象化)、舉具體例子(具體化)、把大問題分解(簡單化)。
- 確認需求與邊界:問清楚輸入範圍、特殊情況(空、極值、非法輸入),先講你會怎麼處理。
- 講出你的方案再寫:先口述做法與複雜度,得到面試官認可再動手。
- 寫乾淨的程式碼:命名清楚、處理邊界(見 工具-防禦式編程)。
- 分析複雜度並嘗試優化:說出時間/空間,思考有沒有更優解(見 工具-演算法設計策略)。
- 測試:用你舉的例子 + 邊界案例走一遍。
★ 走一遍:兩數之和
題目:給一個整數陣列和目標值,找出兩個相加等於目標的元素的索引。
| 步驟 | 你說/做的 |
|---|---|
| 1. 釐清 | 「有沒有可能無解?答案唯一嗎?同一個元素可以用兩次嗎?陣列有沒有排序?數字範圍?」 |
| 2. 舉例 | [2, 7, 11, 15]、目標 9 → [0, 1];邊界:[3, 3]、目標 6 → [0, 1](重複值) |
| 3. 暴力解 | 「兩層迴圈檢查所有配對,O(n²) 時間、O(1) 空間。」——先說出來,表示你有一個可行的基準 |
| 4. 最佳化 | 「內層迴圈其實是在找 target - x 在不在陣列裡,這是查詢問題 → 用 map,O(n) 時間、O(n) 空間。」 |
| 5. 確認再寫 | 「我打算用一次走訪,邊走邊把看過的值存進 map。這樣可以嗎?」 |
| 6. 寫 | 見下 |
| 7. 測試 | 手動跑 [3, 3]、目標 6:i=0 時 map 是空的,存入 3→0;i=1 時找到 3 → 回傳 [0, 1] ✓ |
func twoSum(nums []int, target int) (int, int, bool) {
seen := make(map[int]int, len(nums)) // 值 → 索引
for i, x := range nums {
if j, ok := seen[target-x]; ok {
return j, i, true
}
seen[x] = i // 先查再存:避免同一個元素用兩次
}
return 0, 0, false
}「先查再存」這個順序就是第 2 步舉邊界例子時發現的——如果先存再查,[3] 目標 6 會錯誤地回傳 [0, 0]。
★ 45 分鐘的時間分配
| 階段 | 時間 | 常見錯誤 |
|---|---|---|
| 釐清 + 舉例 | 5 分鐘 | 跳過,然後寫到一半才發現理解錯了 |
| 暴力解 + 最佳化討論 | 10 分鐘 | 直接寫最佳解,卡住時沒有退路 |
| 寫程式 | 15–20 分鐘 | |
| 測試 + 複雜度分析 | 5–10 分鐘 | 說「應該對吧」而不是實際走一遍 |
| 延伸問題 | 剩下的時間 |
★ 每一題都該檢查的邊界案例
- 空的輸入(空陣列、空字串、nil)
- 一個元素
- 全部相同的元素
- 已排序/反向排序
- 最大值/最小值(整數溢位)
- 負數、零
- 重複值
★ 用 Go 面試時要注意的陷阱
| 陷阱 | 說明 |
|---|---|
for _, v := range s 的 v 是副本 | 修改 v 不會改到 slice 裡的元素;要改就用 s[i] |
| map 走訪順序隨機 | 需要確定性輸出就先排序鍵 |
| 子 slice 共用底層陣列 | b := a[1:3] 然後 append(b, x) 可能覆蓋 a[3] |
int 在 64 位元平台是 64 位元 | 溢位的機會比 Java 的 32 位元 int 小,但仍要注意乘法 |
| 沒有內建的堆積、集合、有序 map | 堆積要實作 container/heap 的介面,事先練熟 |
★ 卡住時該說什麼
- 「我先寫暴力解,之後再最佳化。」
- 「我注意到內層迴圈在做重複的工作,想想看能不能記住結果。」
- 「這題讓我想到 X,差別在於 Y。」
- 不要沉默超過一分鐘:面試官沒辦法給你提示,如果他不知道你卡在哪裡。
🧪 我實際套用的紀錄
- 2026-07-15:(待填)
⚠️ 注意
- 沉默寫題是大忌;面試考的是思考過程與溝通,全程 think aloud。
🔗 相關工具
- 工具-程式問題解決策略 —— 底層能力,套路是面試場的表現形式,它是真正的解題方法
- 工具-演算法設計策略 —— 想不出解法時的方向盤,先辨認題型再套策略
- 工具-時間複雜度分析 —— 面試官必問的一環,講得出複雜度才算把題目答完