Giao diện
Phụ lục — Bẫy phỏng vấn DSA thường gặp
Trong phỏng vấn, bạn không thua vì thiếu kiến thức — bạn thua vì rơi vào bẫy. Interviewer thường đặt câu hỏi mà đáp án "hiển nhiên" lại sai. Phụ lục này tổng hợp 30+ bẫy phỏng vấn kinh điển từ mỗi topic family trong Phase 1, giúp bạn nhận diện trước khi bước vào phòng phỏng vấn.
Đọc chậm. Mỗi bẫy đều là một bài học mà ai đó đã trả giá bằng một offer bị từ chối.
🎯 Mục tiêu
Sau khi đọc xong, bạn sẽ:
- Nhận diện 30+ bẫy phỏng vấn phổ biến nhất trong DSA
- Hiểu TẠI SAO mỗi bẫy sai (không chỉ biết đáp án đúng)
- Chuẩn bị câu trả lời chắc chắn cho từng trap trước khi bước vào phòng phỏng vấn
📖 Cách sử dụng trang này
Trang này không phải để đọc một lần. Đây là tài liệu reference — cách dùng hiệu quả nhất:
- Lần đầu: Đọc toàn bộ, đánh dấu những trap bạn đã từng mắc
- Trước phỏng vấn: Review bảng Top 10 + Cheat Sheet ở cuối trang
- Sau khi fail interview: Quay lại xem bạn rơi vào trap nào, ghi chú vào sổ tay
- Khi ôn topic cụ thể: Nhảy thẳng đến section tương ứng (Sorting, Searching, v.v.)
Mỗi bảng trap có 3 cột quan trọng: Bẫy (cái gì sai), Tại sao sai (root cause), Cách đúng (câu trả lời chuẩn). Đừng chỉ nhớ cách đúng — hiểu tại sao sai mới giúp bạn tránh được biến thể của trap.
🫧 Sorting Traps
Sorting là topic "dễ ăn điểm" — nhưng cũng là nơi interviewer cài bẫy nhiều nhất, vì ứng viên hay tự tin quá mức.
| # | Bẫy | Tại sao sai | Cách đúng |
|---|---|---|---|
| 1 | "Bubble Sort luôn O(n²)" | Với swapped flag, best case = O(n) trên sorted data. Nhiều ứng viên quên optimized variant | Phân biệt best / average / worst case. Bubble Sort optimized: best O(n), average & worst O(n²) |
| 2 | "Selection Sort is stable" | Swap phá vỡ relative order. VD: [5a, 5b, 3] → swap 5a với 3 → [3, 5b, 5a] — 5a và 5b đảo vị trí | Selection Sort KHÔNG stable. Muốn stable O(n²) → dùng Insertion Sort |
| 3 | "Hai vòng lặp = O(n²)" | Hai vòng lặp có thể là O(n) nếu tổng iterations ≤ n. VD: two pointers, sliding window — hai con trỏ nhưng mỗi element chỉ được visit tối đa 2 lần | Đếm TỔNG operations, không đếm số vòng lặp. Amortized analysis là chìa khóa |
| 4 | "Quick Sort luôn O(n log n)" | Pivot xấu (first element trên sorted input) → mỗi partition chỉ giảm 1 element → O(n²) | Random pivot hoặc median-of-3. Luôn nói: "average O(n log n), worst O(n²) nếu pivot xấu" |
| 5 | "Heap Sort nhanh hơn Quick Sort" | Worst-case tốt hơn (O(n log n) guaranteed), nhưng average CHẬM hơn do cache locality kém — heap access nhảy lung tung trong memory | Quick Sort nhanh hơn in practice nhờ sequential memory access. Heap Sort chỉ thắng khi cần worst-case guarantee |
| 6 | "Timsort chỉ là Merge Sort" | Timsort exploit natural runs (dãy đã sorted sẵn) + dùng Insertion Sort cho small arrays (< 64 elements) + galloping mode cho merge | Timsort là hybrid adaptive sort, default trong Python và Java. Phân biệt rõ với pure Merge Sort |
| 7 | "Counting Sort luôn O(n)" | Complexity thực tế là O(n + k) với k = range of values. Nếu k >> n (VD: sort 10 số trong range 0–10⁹) thì cực kỳ chậm và tốn memory | Chỉ dùng Counting Sort khi k ≤ n hoặc k là hằng số nhỏ |
Mẹo phỏng vấn
Khi interviewer hỏi về sorting, luôn nói ba complexity: best, average, worst. Đừng chỉ nói "O(n log n)" — đó là câu trả lời incomplete.
🔍 Searching Traps
Binary search nhìn đơn giản nhưng là thuật toán có tỷ lệ bug cao nhất khi implement. Jon Bentley từng nói: chỉ 10% lập trình viên có thể viết binary search đúng lần đầu.
| # | Bẫy | Tại sao sai | Cách đúng |
|---|---|---|---|
| 1 | mid = (lo + hi) / 2 | Integer overflow khi lo + hi > INT_MAX. VD: lo = 2×10⁹, hi = 2×10⁹ → lo + hi tràn số | mid = lo + (hi - lo) / 2 — phép trừ trước, không bao giờ overflow |
| 2 | "Binary Search chỉ cho sorted array" | Binary search on answer: khi answer space là monotonic (nếu x thỏa thì x+1 cũng thỏa), ta binary search trên kết quả | Học pattern search-on-answer: "tìm giá trị nhỏ nhất thỏa điều kiện" |
| 3 | while (lo < hi) với inclusive bounds [lo, hi] | Bỏ sót element cuối khi lo == hi — element đó không bao giờ được check | while (lo <= hi) cho inclusive bounds [lo, hi]. Hoặc dùng while (lo < hi) với exclusive right bound [lo, hi) |
| 4 | hi = mid với while (lo <= hi) | Infinite loop khi lo == hi: mid = lo, hi = mid = lo, loop không bao giờ thoát | Match loop condition với update logic. while (lo <= hi) → hi = mid - 1. while (lo < hi) → hi = mid |
| 5 | "Linear Search luôn tệ hơn Binary Search" | Single query trên unsorted data: sort O(n log n) + binary O(log n) = tổng O(n log n) > linear O(n) | Linear Search tốt cho single query / unsorted data. Binary Search chỉ win khi sort 1 lần + query nhiều lần |
Binary Search Template
Chọn MỘT template và dùng nhất quán. Đừng trộn logic giữa các variant — đó là nguồn gốc của 90% bug binary search.
📦 Data Structure Traps
Data structures là nền tảng, nhưng nhiều ứng viên hiểu sai complexity vì không phân biệt được theoretical vs amortized vs worst-case.
| # | Bẫy | Tại sao sai | Cách đúng |
|---|---|---|---|
| 1 | "Linked List insert O(1)" | Chỉ O(1) khi ĐÃ CÓ reference đến node trước vị trí insert. Nếu phải tìm node đó → traverse O(n) trước | Clarify: insert at known position = O(1), find-then-insert = O(n). Luôn hỏi interviewer: "insert ở đâu?" |
| 2 | "ArrayList.add() is O(n)" | Amortized O(1) vì resize (copy toàn bộ array) chỉ xảy ra khi array đầy — trung bình mỗi add rất rẻ | Hiểu amortized analysis: chi phí resize được "trải đều" cho tất cả operations trước đó |
| 3 | "Stack overflow = bug trong code" | Có thể do recursion quá sâu trên input lớn — code đúng logic nhưng stack frame vượt limit | Dùng iterative approach (explicit stack) cho input lớn. Python default recursion limit = 1000 |
| 4 | "HashMap is O(1) always" | Worst-case O(n) khi tất cả keys hash vào cùng một bucket → degenerate thành linked list | Average O(1), worst O(n). Java 8+ chuyển bucket sang red-black tree khi > 8 elements → worst O(log n) |
| 5 | "Queue = chỉ FIFO" | Deque (double-ended), Priority Queue, Circular Buffer, Monotonic Queue đều là queue variants với behavior khác nhau | Biết các biến thể và khi nào dùng: FIFO cho BFS, Priority Queue cho Dijkstra, Monotonic Queue cho sliding window max |
| 6 | "Array tốt hơn Linked List mọi trường hợp" | LRU Cache: doubly linked list + hash map = O(1) access + O(1) eviction. Array không thể làm điều này efficiently | Linked List tốt cho specific patterns: LRU Cache, undo/redo, polynomial arithmetic, music playlist |
Khi nào nói "O(1)"
Luôn clarify: O(1) amortized hay O(1) worst-case? HashMap get là O(1) amortized nhưng O(n) worst-case. Array access là O(1) worst-case thực sự.
🕸️ Graph Traps
Graph problems chiếm ~25% câu hỏi ở Big Tech interviews. Và graph traps là những bẫy nguy hiểm nhất — vì code chạy đúng trên test case nhỏ nhưng sai hoặc TLE trên input lớn.
| # | Bẫy | Tại sao sai | Cách đúng |
|---|---|---|---|
| 1 | Quên visited set trong BFS/DFS | Infinite loop trên cyclic graph — node A visit B, B visit A, lặp mãi | LUÔN dùng visited set. Đây là rule #1 của graph traversal, không có ngoại lệ (trừ DAG đã confirm) |
| 2 | "Dijkstra cho mọi graph" | Negative weights phá vỡ greedy assumption: Dijkstra finalize node sớm, nhưng negative edge có thể tạo path ngắn hơn sau đó | Negative weights → Bellman-Ford O(VE). Negative cycle detection cũng cần Bellman-Ford |
| 3 | "BFS tìm shortest path mọi graph" | Chỉ đúng cho UNWEIGHTED graph (mỗi edge weight = 1). Weighted graph → BFS cho sai kết quả | Unweighted → BFS. Weighted (non-negative) → Dijkstra. Weighted (có negative) → Bellman-Ford |
| 4 | "DFS cho shortest path" | DFS explore theo chiều sâu, không guarantee tìm path ngắn nhất — nó tìm một path, không phải optimal path | DFS cho: existence check, cycle detection, topological sort, connected components. Shortest path → BFS hoặc Dijkstra |
| 5 | "Adjacency matrix cho mọi graph" | Sparse graph (V=10⁶, E=10⁶): matrix tốn O(V²) = 10¹² cells. Adjacency list chỉ tốn O(V + E) = 2×10⁶ | Adj list cho sparse graph (hầu hết real-world graphs). Matrix cho dense graph hoặc khi cần check edge existence O(1) |
| 6 | Dijkstra không skip visited nodes | Xử lý lại nodes đã finalized → chậm (có thể TLE) hoặc sai kết quả trong edge cases | Thêm if node in visited: continue ngay sau pop từ priority queue. Skip nodes đã có shortest distance |
| 7 | "BFS space = O(V)" | Đúng nhưng misleading. BFS queue có thể chứa O(V) nodes cùng lúc ở worst case (star graph — tất cả nodes connect đến 1 center) | Hiểu space complexity thực tế: BFS trên star graph → queue size = V-1. Trên binary tree balanced → queue size = V/2 ở level cuối |
Bẫy chết người
Quên visited set + cyclic graph = infinite loop trong phỏng vấn. Đây là lỗi #1 khiến ứng viên fail graph questions. Viết visited set TRƯỚC KHI viết BFS/DFS logic.
🧩 Dynamic Programming Traps
DP là topic khó nhất trong interview — không phải vì thuật toán phức tạp, mà vì sai một chi tiết nhỏ = sai toàn bộ kết quả. Không có "gần đúng" trong DP.
| # | Bẫy | Tại sao sai | Cách đúng |
|---|---|---|---|
| 1 | Quên base case | Recursion không bao giờ dừng → stack overflow hoặc wrong answer vì return garbage value | Xác định base cases TRƯỚC KHI viết recurrence. VD: dp[0] = 0, dp[1] = 1 cho Fibonacci |
| 2 | Memoize nhưng quên check cache | Code có memo dict/array nhưng không check trước khi compute → vẫn O(2ⁿ) vì tính lại mọi subproblem | Pattern: if key in memo: return memo[key] TRƯỚC mọi computation. Luôn check trước, tính sau |
| 3 | "Mọi recursion đều là DP" | DP cần overlapping subproblems. Binary search là recursive nhưng KHÔNG phải DP — mỗi subproblem chỉ xuất hiện 1 lần | Kiểm tra 2 trụ cột: (1) Optimal substructure, (2) Overlapping subproblems. Thiếu một → không phải DP |
| 4 | Sai state definition | State không capture đủ information → wrong answer. VD: knapsack chỉ track value mà quên track remaining capacity | State phải chứa đủ information để quyết định mọi subproblem. Thêm dimension nếu cần |
| 5 | Off-by-one trong dp array | dp = [0] * n thay vì dp = [0] * (n + 1) → index out of bounds khi access dp[n] | Size = n + 1 khi dp[i] đại diện cho "dùng i items" (i từ 0 đến n). Vẽ bảng trước khi code |
| 6 | "Top-down luôn tốt hơn bottom-up" | Top-down (memoization): stack overflow cho n lớn, cache behavior kém. Bottom-up (tabulation): no stack, sequential memory access | Bottom-up cho n lớn (> 10⁴), top-down khi logic phức tạp hoặc chỉ cần một phần state space |
DP Checklist trước khi code
- ✅ Xác định state — cần bao nhiêu dimensions?
- ✅ Viết recurrence relation trên giấy
- ✅ Xác định base cases — mọi recursion path đều phải reach base case
- ✅ Chọn top-down hay bottom-up dựa trên constraint
- ✅ Kiểm tra array size — off-by-one là bug phổ biến nhất
⚙️ General Interview Traps
Những bẫy này không thuộc topic cụ thể nào — chúng là meta-traps về cách bạn approach interview. Rơi vào đây thì dù thuật toán đúng, bạn vẫn fail.
| # | Bẫy | Tại sao sai | Cách đúng |
|---|---|---|---|
| 1 | Code ngay không hỏi clarifying questions | Có thể giải sai bài hoặc miss edge cases mà interviewer cố tình giấu | Hỏi trước khi code: input range? duplicates? sorted? negative numbers? empty input? |
| 2 | Premature optimization | Optimize O(n²) → O(n log n) trong khi constraint n ≤ 100 — lãng phí thời gian, tăng complexity, dễ bug | Giải brute-force đúng trước → analyze complexity → optimize chỉ khi cần |
| 3 | Bỏ qua edge cases | Empty array, single element, all same values, INT_MAX, INT_MIN, negative numbers — mỗi cái là một bug tiềm ẩn | Luôn test: [], [x], [x, x, x], extreme values. Nói ra edge cases trước khi interviewer hỏi |
| 4 | Không nói complexity analysis | Interviewer muốn nghe bạn phân tích — code đúng mà không analyze = chỉ đạt 50% điểm | State time + space complexity cho EVERY solution. So sánh trade-offs giữa approaches |
| 5 | "Tôi biết cách giải nhưng không code được" | Kiến thức ≠ kỹ năng implementation. Biết Quick Sort work nhưng không viết được partition = fail | Practice coding, không chỉ đọc lý thuyết. Mỗi algorithm, viết ít nhất 3 lần từ đầu |
| 6 | Không communicate trong lúc code | Im lặng 20 phút → interviewer không biết bạn đang nghĩ gì → không thể cho hint hoặc partial credit | Think aloud: nói approach, trade-offs, tại sao chọn data structure này. Interviewer đánh giá process, không chỉ result |
Quy tắc 5 phút
Nếu bạn stuck hơn 5 phút mà không tiến triển — nói ra. "I'm stuck on X, let me think about a different approach" tốt hơn im lặng. Interviewer sẽ cho hint, và nhận hint không phải là điểm trừ.
🏆 Top 10 Interview Traps — Xếp hạng theo tần suất
Từ 30+ bẫy ở trên, đây là 10 bẫy xuất hiện nhiều nhất trong phỏng vấn thực tế, xếp hạng theo tần suất ứng viên mắc phải:
| Hạng | Bẫy | Topic | Mức độ nguy hiểm |
|---|---|---|---|
| 🥇 1 | Integer overflow trong binary search mid = (lo + hi) / 2 | Searching | 🔴 Critical |
| 🥈 2 | Quên visited set trong graph traversal | Graph | 🔴 Critical |
| 🥉 3 | Dijkstra với negative weights — vẫn dùng Dijkstra khi graph có negative edges | Graph | 🔴 Critical |
| 4 | Quên base case trong DP — recursion chạy mãi không dừng | DP | 🔴 Critical |
| 5 | Selection Sort is stable — trả lời sai khi interviewer hỏi stable sort | Sorting | 🟡 High |
| 6 | while (lo < hi) vs while (lo <= hi) — mismatch loop condition với update logic | Searching | 🟡 High |
| 7 | HashMap "always O(1)" — quên worst-case O(n) | Data Structures | 🟡 High |
| 8 | Hai nested loops = O(n²) — không phải lúc nào cũng đúng (two pointers, sliding window) | Sorting / General | 🟡 High |
| 9 | Quick Sort worst-case trên sorted input với first-element pivot | Sorting | 🟠 Medium |
| 10 | Memoization không check cache — có memo nhưng quên if key in memo | DP | 🟠 Medium |
💡 Pro tip: In danh sách này ra, dán lên tường phòng ngủ, review mỗi tối trước ngày phỏng vấn. Nghiêm túc.
Tại sao top 3 đều là "Critical"?
Vì cả 3 đều gây ra kết quả sai hoàn toàn (không phải chậm, không phải suboptimal — mà SAI):
- Integer overflow:
midsai → search sai vùng → trả về -1 khi answer tồn tại. Trong production: crash, security vulnerability - Quên visited: Infinite loop → chương trình treo → timeout trong interview, OOM trong production
- Dijkstra + negative weights: Trả về shortest path sai — Dijkstra vẫn return giá trị, nhưng giá trị đó không phải minimum. Âm thầm sai là nguy hiểm nhất
Còn các trap hạng 5-10 thường gây suboptimal answer hoặc incomplete analysis — vẫn mất điểm nhưng không fatal.
🧪 Practice: Kiểm tra kiến thức
🧠 Quiz — Scenario Choice
Tình huống: Interviewer cho bạn một graph có negative weights và yêu cầu tìm shortest path. Bạn đề xuất Dijkstra. Interviewer nhíu mày hỏi: "Bạn chắc chưa?"
Bạn nên làm gì?
A. Giữ nguyên Dijkstra — worst-case vẫn cho kết quả gần đúng
B. Chuyển sang Bellman-Ford — vì Dijkstra không handle negative weights
C. Hỏi thêm: "Graph có negative cycle không?" — rồi quyết định Bellman-Ford hoặc báo impossible
D. Dùng BFS — vì BFS luôn tìm shortest path
💡 Đáp án & Giải thích
Đáp án đúng: C
- A sai: Dijkstra với negative weights cho kết quả SAI (không phải gần đúng — hoàn toàn sai) vì greedy assumption bị phá vỡ
- B đúng một phần: Bellman-Ford handle negative weights, nhưng nếu có negative cycle thì shortest path không tồn tại (có thể đi vòng mãi để giảm cost)
- C đúng nhất: Hỏi clarifying question trước → nếu không có negative cycle → Bellman-Ford. Nếu có negative cycle → báo "shortest path undefined"
- D sai: BFS chỉ cho shortest path trên unweighted graph
Bài học: Luôn hỏi clarifying questions. Interviewer hỏi "chắc chưa?" là đang cho bạn cơ hội sửa sai — hãy tận dụng.
🐛 Spot the Bug
Đoạn code binary search dưới đây có HAI bugs. Tìm cả hai:
python
def binary_search(arr, target):
lo = 0
hi = len(arr) - 1
while lo < hi: # 🐛 Bug #1
mid = (lo + hi) / 2 # 🐛 Bug #2
if arr[mid] == target:
return mid
elif arr[mid] < target:
lo = mid + 1
else:
hi = mid - 1
return -1🔍 Phân tích bugs
Bug #1: while lo < hi — sai loop condition
Với inclusive bounds [lo, hi], khi lo == hi vẫn còn 1 element chưa check. Nếu target nằm ở vị trí đó → trả về -1 sai.
python
# ❌ Sai: bỏ sót element khi lo == hi
while lo < hi:
# ✅ Đúng: check cả khi lo == hi
while lo <= hi:Bug #2: mid = (lo + hi) / 2 — hai lỗi trong một dòng
- Integer overflow:
lo + hicó thể tràn số (trong C/C++/Java). Python không bị nhưng đây là bad habit - Python-specific:
/trả về float trong Python 3 →arr[mid]báo lỗi TypeError vì index phải là int
python
# ❌ Sai: overflow risk + float division
mid = (lo + hi) / 2
# ✅ Đúng: no overflow + integer division
mid = lo + (hi - lo) // 2Code đã fix:
python
def binary_search(arr, target):
lo = 0
hi = len(arr) - 1
while lo <= hi: # ✅ Fixed
mid = lo + (hi - lo) // 2 # ✅ Fixed
if arr[mid] == target:
return mid
elif arr[mid] < target:
lo = mid + 1
else:
hi = mid - 1
return -1🎭 Scenario: Mock Interview Replay
Bối cảnh: Ứng viên được hỏi bài Two Sum — tìm hai số trong array có tổng bằng target.
Ứng viên: "Dùng hai vòng for lồng nhau, check mọi cặp. O(n²)."
Interviewer: "Có cách nào nhanh hơn không?"
Ứng viên: Im lặng 3 phút...
Interviewer: "Nếu bạn đã thấy một số, bạn biết cần tìm số nào tiếp theo?"
Ứng viên: "À! Dùng HashMap — với mỗi số
x, check xemtarget - xcó trong map không. O(n)!"Interviewer: "HashMap O(1) luôn phải không?"
🎯 Phân tích
Ứng viên rơi vào 3 traps:
Trap #1 — Không communicate (General Trap #6): Im lặng 3 phút thay vì nói ra hướng suy nghĩ. Interviewer phải chủ động cho hint.
Trap #2 — "HashMap always O(1)" (Data Structure Trap #4): Câu trả lời đúng là: "Average O(1) per lookup, nên overall là O(n) average. Worst-case nếu hash collision xấu thì O(n) per lookup → O(n²) worst-case, nhưng điều này cực hiếm với good hash function."
Trap #3 — Không hỏi clarifying questions (General Trap #1): Trước khi code, nên hỏi:
- Array có sorted không? (Nếu có → two pointers O(n) không cần extra space)
- Có duplicate không? (Ảnh hưởng đến HashMap logic)
- Có chính xác 1 solution hay nhiều? (Ảnh hưởng đến return type)
Bài học: Kỹ năng communicate và clarify quan trọng ngang bằng kỹ năng thuật toán.
🎭 Scenario 2: DP State Trap
Bối cảnh: Ứng viên được hỏi bài 0/1 Knapsack — chọn items có weight và value để maximize value trong capacity W.
Ứng viên: "Dùng DP. State là
dp[i]= max value khi xét i items đầu tiên."Interviewer: "State đó đủ chưa? Nếu bạn biết max value khi xét 3 items đầu — bạn có biết còn bao nhiêu capacity để xét item thứ 4 không?"
Ứng viên: Im lặng...
Interviewer: "State cần capture thêm information gì?"
🎯 Phân tích
Ứng viên mắc DP Trap #4 — Sai state definition:
dp[i]chỉ track "xét i items" nhưng không track remaining capacity- Không biết còn bao nhiêu capacity → không thể quyết định có pick item tiếp theo không
- State đúng:
dp[i][w]= max value khi xét i items đầu tiên VỚI capacity = w - Cần 2 dimensions: item index + remaining capacity
Quy tắc chọn state DP: State phải chứa đủ information để từ bất kỳ state nào, bạn có thể quyết định optimal action mà không cần biết gì thêm. Nếu thiếu info → thêm dimension.
✅ Trap Prevention Checklist
Checklist này dùng trước và trong phỏng vấn. Print ra hoặc ghi nhớ:
Trước khi code (2-3 phút):
- [ ] Hỏi clarifying questions: input range, edge cases, constraints
- [ ] Nói approach + complexity trước khi viết code
- [ ] Xác nhận: sorted? duplicates? negative numbers? empty input?
Trong khi code:
- [ ] Binary search: dùng
lo + (hi - lo) // 2, không dùng(lo + hi) / 2 - [ ] Graph: viết
visited = set()TRƯỚC khi viết BFS/DFS - [ ] DP: viết base cases TRƯỚC recurrence
- [ ] Array size:
n + 1khi dp index chạy từ 0 đến n
Sau khi code (1-2 phút):
- [ ] Dry-run qua ít nhất 1 example
- [ ] Test edge cases: empty, single element, all same, extreme values
- [ ] State time complexity + space complexity
📋 Cheat Sheet — Quick Reference
Bảng tóm tắt để review nhanh trước phỏng vấn:
| Topic | Bẫy nguy hiểm nhất | Một câu để nhớ |
|---|---|---|
| Sorting | "Quick Sort luôn O(n log n)" | "Average ≠ Worst. Sorted input + bad pivot = O(n²)" |
| Searching | mid = (lo + hi) / 2 | "Trừ trước, chia sau: lo + (hi - lo) / 2" |
| Data Structures | "HashMap O(1) always" | "Average O(1), worst O(n). Nói amortized!" |
| Graph | Quên visited set | "Viết visited TRƯỚC khi viết BFS/DFS" |
| DP | Quên base case | "Base case trước, recurrence sau" |
| General | Code ngay không hỏi | "5 phút clarify tiết kiệm 20 phút debug" |
📍 Trang tiếp theo
Bạn đã nắm vững các bẫy phỏng vấn DSA. Tiếp theo, hãy xem cách kiến thức DSA kết nối trực tiếp với System Design — kỹ năng mà mọi senior engineer đều cần: