Buổi 13 — Final Mock: FAANG Mastery Complete
Navigation
← 12-Practice-FAANG-1 | → Roadmap-FAANG Giai đoạn: FAANG Mastery | Loại: Final Assessment
1. Final Assessment Overview
Đây là buổi culminating session — mô phỏng hoàn chỉnh một FAANG on-site loop thực tế. Tại các công ty như Google, Meta, Amazon: một on-site loop thường gồm 4-5 interview rounds kéo dài cả ngày. Buổi này simulate 3 rounds chính.
Cách dùng buổi này hiệu quả nhất
Option A — Full Simulation: Đặt timer 45 phút/round, tắt solutions, làm như interview thật. Sau đó mới mở xem. Option B — Study Mode: Đọc problem, tự nghĩ approach 10 phút, rồi đọc solution và phân tích. Recommend: làm Option A ít nhất 1 lần trước ngày phỏng vấn thật.
Cấu trúc buổi:
| Round | Focus | Problem | Thời gian |
|---|---|---|---|
| Round 1 | Coding Interview | #295 Find Median from Data Stream | 45 phút |
| Round 2 | Algorithm Design | #23 Merge K Sorted Lists | 45 phút |
| Round 3 | System-Level Algorithm | #297 Serialize and Deserialize Binary Tree | 45 phút |
2. Round 1 — Coding Interview (45 phút)
Problem: #295 Find Median from Data Stream (Hard)
Đề bài: Design một data structure hỗ trợ 2 operations:
addNum(num): Thêm số nguyênnumtừ data streamfindMedian(): Trả về median của tất cả số đã thêm
Ví dụ:
addNum(1) → stream: [1] → median = 1.0
addNum(2) → stream: [1, 2] → median = 1.5
addNum(3) → stream: [1, 2, 3] → median = 2.0
addNum(4) → stream: [1,2,3,4] → median = 2.5
Clarifying questions:
- Số lượng addNum calls tối đa? → Lên đến 5 × 10⁴
- Có số âm không? → Có, trong range [-10⁵, 10⁵]
- findMedian được gọi bao nhiêu lần? → Lên đến 5 × 10⁴
Key insight — Tại sao dùng 2 Heaps?
- Median là phần tử “ở giữa” của dãy đã sort
- maxHeap (lower half): chứa nửa nhỏ, root = phần tử lớn nhất của nửa nhỏ
- minHeap (upper half): chứa nửa lớn, root = phần tử nhỏ nhất của nửa lớn
- Median = root của maxHeap (nếu lẻ) hoặc trung bình 2 roots (nếu chẵn)
// MedianFinder — Two Heaps approach
// addNum: O(log N) | findMedian: O(1)
// Space: O(N)
// TypeScript không có built-in Heap, phải implement MinHeap và MaxHeap
class MinHeap {
private data: number[] = [];
push(val: number): void {
this.data.push(val);
this.bubbleUp(this.data.length - 1);
}
pop(): number {
if (this.data.length === 1) return this.data.pop()!;
const top = this.data[0];
this.data[0] = this.data.pop()!;
this.sinkDown(0);
return top;
}
peek(): number {
return this.data[0];
}
size(): number {
return this.data.length;
}
private bubbleUp(i: number): void {
while (i > 0) {
const parent = Math.floor((i - 1) / 2);
if (this.data[parent] <= this.data[i]) break;
[this.data[parent], this.data[i]] = [this.data[i], this.data[parent]];
i = parent;
}
}
private sinkDown(i: number): void {
const n = this.data.length;
while (true) {
let smallest = i;
const left = 2 * i + 1;
const right = 2 * i + 2;
if (left < n && this.data[left] < this.data[smallest]) smallest = left;
if (right < n && this.data[right] < this.data[smallest]) smallest = right;
if (smallest === i) break;
[this.data[smallest], this.data[i]] = [this.data[i], this.data[smallest]];
i = smallest;
}
}
}
class MaxHeap {
private data: number[] = [];
push(val: number): void {
this.data.push(val);
this.bubbleUp(this.data.length - 1);
}
pop(): number {
if (this.data.length === 1) return this.data.pop()!;
const top = this.data[0];
this.data[0] = this.data.pop()!;
this.sinkDown(0);
return top;
}
peek(): number {
return this.data[0];
}
size(): number {
return this.data.length;
}
private bubbleUp(i: number): void {
while (i > 0) {
const parent = Math.floor((i - 1) / 2);
if (this.data[parent] >= this.data[i]) break;
[this.data[parent], this.data[i]] = [this.data[i], this.data[parent]];
i = parent;
}
}
private sinkDown(i: number): void {
const n = this.data.length;
while (true) {
let largest = i;
const left = 2 * i + 1;
const right = 2 * i + 2;
if (left < n && this.data[left] > this.data[largest]) largest = left;
if (right < n && this.data[right] > this.data[largest]) largest = right;
if (largest === i) break;
[this.data[largest], this.data[i]] = [this.data[i], this.data[largest]];
i = largest;
}
}
}
class MedianFinder {
// maxHeap: nửa nhỏ hơn (lower half), root = max của nửa này
private lowerHalf: MaxHeap;
// minHeap: nửa lớn hơn (upper half), root = min của nửa này
private upperHalf: MinHeap;
constructor() {
this.lowerHalf = new MaxHeap();
this.upperHalf = new MinHeap();
}
addNum(num: number): void {
// Bước 1: Thêm vào lowerHalf trước
this.lowerHalf.push(num);
// Bước 2: Đảm bảo tất cả phần tử ở lowerHalf ≤ tất cả phần tử ở upperHalf
// Nếu max(lowerHalf) > min(upperHalf) → vi phạm invariant → rebalance
if (
this.upperHalf.size() > 0 &&
this.lowerHalf.peek() > this.upperHalf.peek()
) {
this.upperHalf.push(this.lowerHalf.pop());
}
// Bước 3: Balance kích thước — lowerHalf được phép có nhiều hơn 1 phần tử
// (khi tổng số phần tử lẻ, lowerHalf chứa median)
if (this.lowerHalf.size() > this.upperHalf.size() + 1) {
this.upperHalf.push(this.lowerHalf.pop());
} else if (this.upperHalf.size() > this.lowerHalf.size()) {
this.lowerHalf.push(this.upperHalf.pop());
}
}
findMedian(): number {
// Tổng số phần tử lẻ → median là root của lowerHalf
if (this.lowerHalf.size() > this.upperHalf.size()) {
return this.lowerHalf.peek();
}
// Tổng số phần tử chẵn → median là trung bình 2 roots
return (this.lowerHalf.peek() + this.upperHalf.peek()) / 2;
}
}
// Test
const medianFinder = new MedianFinder();
medianFinder.addNum(1);
console.log(medianFinder.findMedian()); // 1.0
medianFinder.addNum(2);
console.log(medianFinder.findMedian()); // 1.5
medianFinder.addNum(3);
console.log(medianFinder.findMedian()); // 2.0
medianFinder.addNum(4);
console.log(medianFinder.findMedian()); // 2.5Complexity Analysis:
| Operation | Time | Space |
|---|---|---|
addNum | O(log N) | — |
findMedian | O(1) | — |
| Overall Space | — | O(N) |
Follow-up questions thường gặp
Q: Nếu số liệu lệch nhiều (99% < 100, 1% > 1000000), có optimize được không? A: Dùng Bucketing hoặc Order Statistics Tree (Red-Black Tree). Trong phỏng vấn, mention được đây là follow-up quan trọng.
3. Round 2 — Algorithm Design (45 phút)
Problem: #23 Merge K Sorted Lists (Hard)
Đề bài: Cho mảng lists gồm K linked lists đã sort tăng dần. Merge tất cả thành 1 linked list đã sort.
Ví dụ:
Input: lists = [[1,4,5], [1,3,4], [2,6]]
Output: [1, 1, 2, 3, 4, 4, 5, 6]
Clarifying questions:
- K có thể là 0 (empty array) không? → Có, trả về null
- Lists có thể có linked list rỗng không? → Có
- Tổng số nodes N là bao nhiêu? → N ≤ 10⁴
Approach 1: Priority Queue — O(N log K)
class ListNode {
val: number;
next: ListNode | null;
constructor(val = 0, next: ListNode | null = null) {
this.val = val;
this.next = next;
}
}
// Priority Queue (Min-Heap) cho ListNode
// So sánh theo val của node
class NodeMinHeap {
private data: ListNode[] = [];
push(node: ListNode): void {
this.data.push(node);
this.bubbleUp(this.data.length - 1);
}
pop(): ListNode {
if (this.data.length === 1) return this.data.pop()!;
const top = this.data[0];
this.data[0] = this.data.pop()!;
this.sinkDown(0);
return top;
}
peek(): ListNode {
return this.data[0];
}
size(): number {
return this.data.length;
}
private bubbleUp(i: number): void {
while (i > 0) {
const parent = Math.floor((i - 1) / 2);
if (this.data[parent].val <= this.data[i].val) break;
[this.data[parent], this.data[i]] = [this.data[i], this.data[parent]];
i = parent;
}
}
private sinkDown(i: number): void {
const n = this.data.length;
while (true) {
let smallest = i;
const left = 2 * i + 1;
const right = 2 * i + 2;
if (left < n && this.data[left].val < this.data[smallest].val) smallest = left;
if (right < n && this.data[right].val < this.data[smallest].val) smallest = right;
if (smallest === i) break;
[this.data[smallest], this.data[i]] = [this.data[i], this.data[smallest]];
i = smallest;
}
}
}
// Approach 1: Priority Queue
// Ý tưởng: duy trì heap gồm K nodes đang ở "đầu" của mỗi list
// Mỗi lần lấy min ra, thêm node tiếp theo của list đó vào heap
// Time: O(N log K) — mỗi node push/pop heap 1 lần, heap size luôn ≤ K
// Space: O(K) — heap chứa tối đa K nodes
function mergeKLists_Heap(lists: (ListNode | null)[]): ListNode | null {
const heap = new NodeMinHeap();
const dummy = new ListNode(0); // Sentinel node để đơn giản hóa code
let current = dummy;
// Thêm head của từng list vào heap (bỏ qua null nodes)
for (const head of lists) {
if (head !== null) heap.push(head);
}
while (heap.size() > 0) {
// Lấy node nhỏ nhất từ heap
const minNode = heap.pop();
current.next = minNode;
current = current.next;
// Nếu node đó có next → thêm next vào heap
if (minNode.next !== null) {
heap.push(minNode.next);
}
}
return dummy.next;
}Approach 2: Divide & Conquer — O(N log K)
// Approach 2: Divide & Conquer
// Ý tưởng: merge từng cặp list lại → giảm K lists xuống K/2 lists → lặp lại
// Giống merge sort: log K rounds, mỗi round merge tổng N nodes
// Time: O(N log K) | Space: O(log K) cho call stack
function mergeKLists_DivideConquer(lists: (ListNode | null)[]): ListNode | null {
if (lists.length === 0) return null;
let interval = 1;
// Mỗi vòng lặp: merge từng cặp lists[i] với lists[i + interval]
while (interval < lists.length) {
for (let i = 0; i + interval < lists.length; i += interval * 2) {
lists[i] = mergeTwoLists(lists[i], lists[i + interval]);
}
interval *= 2;
}
return lists[0];
}
// Helper: merge 2 sorted linked lists (classic problem #21)
// Time: O(m + n) | Space: O(1)
function mergeTwoLists(
l1: ListNode | null,
l2: ListNode | null
): ListNode | null {
const dummy = new ListNode(0);
let current = dummy;
while (l1 !== null && l2 !== null) {
if (l1.val <= l2.val) {
current.next = l1;
l1 = l1.next;
} else {
current.next = l2;
l2 = l2.next;
}
current = current.next;
}
// Nối phần còn lại (1 trong 2 list chưa hết)
current.next = l1 ?? l2;
return dummy.next;
}
// Helper để tạo linked list từ array (cho testing)
function arrayToList(arr: number[]): ListNode | null {
const dummy = new ListNode(0);
let cur = dummy;
for (const v of arr) { cur.next = new ListNode(v); cur = cur.next; }
return dummy.next;
}
// Helper để convert list sang array (cho testing)
function listToArray(head: ListNode | null): number[] {
const res: number[] = [];
while (head) { res.push(head.val); head = head.next; }
return res;
}
// Test
const lists = [
arrayToList([1, 4, 5]),
arrayToList([1, 3, 4]),
arrayToList([2, 6]),
];
console.log(listToArray(mergeKLists_Heap([...lists]))); // [1,1,2,3,4,4,5,6]
console.log(listToArray(mergeKLists_DivideConquer([...lists]))); // [1,1,2,3,4,4,5,6]So sánh 2 approaches
Priority Queue Divide & Conquer Time O(N log K) O(N log K) Space O(K) heap O(log K) stack Practical Dễ code hơn Elegant, no external heap Interview Mention cả 2, code Heap trước Code nếu còn thời gian Tại sao cùng complexity? Cả 2 đều xử lý mỗi node log K lần. Heap approach: log K per heap op. D&C approach: log K merge rounds.
4. Round 3 — System-Level Algorithm (45 phút)
Problem: #297 Serialize and Deserialize Binary Tree (Hard)
Đề bài: Design thuật toán để:
serialize(root): Convert binary tree thành stringdeserialize(data): Convert string lại thành binary tree
Ví dụ:
Input tree: 1
/ \
2 3
/ \
4 5
serialize → "1,2,null,null,3,4,null,null,5,null,null" (ví dụ DFS)
deserialize → reconstruct lại tree ban đầu
Approach 1: BFS (Level-Order Serialization)
class TreeNode {
val: number;
left: TreeNode | null;
right: TreeNode | null;
constructor(val = 0, left: TreeNode | null = null, right: TreeNode | null = null) {
this.val = val;
this.left = left;
this.right = right;
}
}
// Approach 1: BFS — Level-order traversal
// Giống cách LeetCode hiển thị tree: "1,2,3,null,null,4,5"
// Time: O(N) | Space: O(N)
class BFSCodec {
// Serialize: BFS, ghi từng node theo level order
// null node ghi là "null"
serialize(root: TreeNode | null): string {
if (root === null) return "";
const result: string[] = [];
const queue: (TreeNode | null)[] = [root];
let head = 0; // Index pointer — O(1) dequeue (xem 03-Stack-and-Queue § Pitfall 2)
while (head < queue.length) {
const node = queue[head++];
if (node === null) {
result.push("null");
} else {
result.push(String(node.val));
// Thêm cả null children vào queue để serialize đầy đủ
queue.push(node.left);
queue.push(node.right);
}
}
return result.join(",");
}
// Deserialize: đọc lần lượt, dùng queue để biết node nào đang cần children
deserialize(data: string): TreeNode | null {
if (data === "") return null;
const values = data.split(",");
const root = new TreeNode(parseInt(values[0]));
const queue: TreeNode[] = [root];
let head = 0; // Index pointer
let i = 1; // index trong values array
while (head < queue.length && i < values.length) {
const node = queue[head++];
// Gán left child
if (values[i] !== "null") {
node.left = new TreeNode(parseInt(values[i]));
queue.push(node.left);
}
i++;
// Gán right child
if (i < values.length && values[i] !== "null") {
node.right = new TreeNode(parseInt(values[i]));
queue.push(node.right);
}
i++;
}
return root;
}
}Approach 2: DFS (Preorder Serialization)
// Approach 2: DFS — Preorder traversal (root, left, right)
// Elegant recursive solution, dễ implement
// Time: O(N) | Space: O(N) — call stack O(H)
class DFSCodec {
// Serialize: preorder DFS
// Format: "1,2,null,null,3,4,null,null,5,null,null"
serialize(root: TreeNode | null): string {
const parts: string[] = [];
function dfs(node: TreeNode | null): void {
if (node === null) {
parts.push("null");
return;
}
parts.push(String(node.val)); // Pre-order: root trước
dfs(node.left); // rồi left
dfs(node.right); // rồi right
}
dfs(root);
return parts.join(",");
}
// Deserialize: dùng index pointer (hoặc iterator) để đọc từng giá trị
deserialize(data: string): TreeNode | null {
const values = data.split(",");
let index = 0; // pointer vào values array
function buildTree(): TreeNode | null {
if (index >= values.length || values[index] === "null") {
index++; // consume "null" token
return null;
}
const node = new TreeNode(parseInt(values[index]));
index++; // consume current value
node.left = buildTree(); // recursively build left subtree
node.right = buildTree(); // recursively build right subtree
return node;
}
return buildTree();
}
}
// Test cả 2 approaches
function treeToArray(root: TreeNode | null): (number | null)[] {
if (!root) return [];
const res: (number | null)[] = [];
const q: (TreeNode | null)[] = [root];
let head = 0;
while (head < q.length) {
const n = q[head++];
if (n === null) { res.push(null); continue; }
res.push(n.val);
q.push(n.left, n.right);
}
// trim trailing nulls
while (res[res.length - 1] === null) res.pop();
return res;
}
const tree = new TreeNode(1,
new TreeNode(2),
new TreeNode(3, new TreeNode(4), new TreeNode(5))
);
const bfsCodec = new BFSCodec();
const serializedBFS = bfsCodec.serialize(tree);
console.log("BFS serialized:", serializedBFS);
console.log("BFS deserialized:", treeToArray(bfsCodec.deserialize(serializedBFS)));
const dfsCodec = new DFSCodec();
const serializedDFS = dfsCodec.serialize(tree);
console.log("DFS serialized:", serializedDFS);
console.log("DFS deserialized:", treeToArray(dfsCodec.deserialize(serializedDFS)));Khi nào dùng BFS vs DFS serialize?
- BFS: dễ visualize, output giống LeetCode format, tốt cho “wide” trees
- DFS Preorder: code ngắn gọn hơn, recursive elegant, tốt cho interview khi muốn impress
- Cả 2 đều O(N) time/space — interviewer thường chấp nhận cả 2
5. Complete FAANG Readiness Checklist
Checklist này cover toàn bộ 25 buổi của vault. Tick khi cảm thấy tự tin giải được trong interview (không chỉ hiểu khi đọc).
Big Tech Foundation (Buổi 1-10)
- Complexity Analysis: Phân tích được Time/Space cho bất kỳ algorithm nào, biết Master Theorem
- Array & String: Prefix Sum, Kadane’s Algorithm, Two-pass scan, in-place manipulation
- Linked List: Reverse, cycle detection (Floyd’s), merge, find middle (slow/fast pointers)
- Stack & Queue: Monotonic stack, implement queue via stacks, expression evaluation
- HashMap & HashSet: Frequency counting, grouping anagrams, two-sum pattern
- Binary Search: Standard template, rotated array, search space reduction (không chỉ sorted array!)
- Two Pointers: Same direction, opposite direction, giải được Container With Most Water, 3Sum
- Sliding Window: Fixed size và variable size, giải được Minimum Window Substring
- Tree Traversal: BFS (level order), DFS (pre/in/post), giải được LCA, path sum problems
- Sorting Algorithms: Biết implement QuickSort và MergeSort, hiểu khi nào dùng cái nào
FAANG Mastery (Buổi 11-13)
- Segment Tree: Build, range query, point update — giải được Range Sum Query Mutable
- Binary Indexed Tree (Fenwick): Alternative cho Segment Tree, code ngắn hơn
- Graph - BFS/DFS: Shortest path (unweighted), connected components, bipartite check
- Graph - Dijkstra: Shortest path weighted graph, giải được Network Delay Time
- Graph - Topological Sort: Kahn’s BFS và DFS approach, giải được Course Schedule I & II
- Union Find: Path compression + rank, giải được Number of Islands II, Redundant Connection
- Heap/Priority Queue: Custom comparator, giải được Merge K Lists, Find Median from Stream
- Dynamic Programming - 1D: Fibonacci pattern, Climbing Stairs, House Robber, Coin Change
- Dynamic Programming - 2D: Grid DP, Edit Distance, Longest Common Subsequence
- DP - Knapsack: 0/1 Knapsack, Unbounded Knapsack, Partition Equal Subset Sum
- Backtracking: Permutations, Combinations, Subsets, N-Queens, Sudoku Solver
- Greedy: Activity Selection, Jump Game, Meeting Rooms, biết phân biệt với DP
- Trie: Insert/Search/StartsWith, giải được Word Search II
- Bit Manipulation: AND/OR/XOR tricks, single number, count bits, power of two
- Math & Geometry: GCD/LCM, prime sieve, matrix rotation
Cách dùng checklist này
Với mỗi topic chưa tick: mở LeetCode, tìm 2-3 bài medium, giải trong 30 phút không xem solution. Nếu làm được → tick. Nếu không → quay lại học lại buổi đó.
6. Interview Readiness Score
Tự đánh giá từng topic từ 1-10, tính weighted average để có Overall FAANG Score.
Hướng dẫn chấm điểm
- 1-3: Còn nhớ mang máng, cần xem lại từ đầu
- 4-6: Hiểu concept, làm được medium với một ít struggle
- 7-8: Tự tin làm medium trong 20-25 phút, biết cách approach hard
- 9-10: Làm được hard trong 30-35 phút, giải thích được cho người khác
| Topic | Trọng số | Score (1-10) | Weighted |
|---|---|---|---|
| Array / String / HashMap | 15% | __ | __ |
| Binary Search | 8% | __ | __ |
| Two Pointers / Sliding Window | 10% | __ | __ |
| Tree (BFS/DFS) | 10% | __ | __ |
| Graph (BFS/DFS/Topo) | 10% | __ | __ |
| Dynamic Programming | 15% | __ | __ |
| Heap / Priority Queue | 8% | __ | __ |
| Backtracking | 7% | __ | __ |
| Union Find | 5% | __ | __ |
| Greedy | 5% | __ | __ |
| Bit Manipulation | 4% | __ | __ |
| Trie / Segment Tree | 3% | __ | __ |
| OVERALL SCORE | 100% | __ |
Ý nghĩa Overall Score:
| Score | Ý nghĩa | Hành động |
|---|---|---|
| ≥ 8.0 | FAANG Ready | Đặt lịch phỏng vấn ngay |
| 7.0 - 7.9 | Almost There | 2-3 tuần luyện thêm weak areas |
| 6.0 - 6.9 | On Track | 1-2 tháng luyện thêm, focus vào DP + Graph |
| < 6.0 | Need More Time | Review lại fundamentals, làm thêm 50 easy/medium |
7. Next Steps After This Vault
Roadmap 60 ngày sau vault
Mục tiêu: không bị lãng quên kiến thức và xây dựng pattern recognition thực sự qua problems mới.
Luyện tập có cấu trúc
Tuần 1-2: Ôn lại và củng cố
- Làm lại tất cả problems trong vault từ đầu, không xem solution
- Ghi ra các patterns và templates vào notebook riêng
- Fix các topics có score < 7 trong readiness score
Tuần 3-8: 50 LeetCode Problems mới Phân bổ theo tần suất xuất hiện trong FAANG interviews:
- 10 bài DP (mix 1D và 2D)
- 8 bài Graph (mix BFS/DFS/Dijkstra)
- 8 bài Tree (Binary Tree + BST)
- 7 bài Array/String (Sliding Window + Two Pointers)
- 5 bài Backtracking
- 5 bài Heap/Priority Queue
- 4 bài Binary Search
- 3 bài Union Find / Trie
Quy tắc mỗi bài:
- Đặt timer 30 phút (Medium) hoặc 45 phút (Hard)
- Nếu không giải được sau 2/3 thời gian → ghi lại pattern đang bí
- Sau khi giải: đọc top discussions, học cách người khác tối ưu
Mock Interview Platforms
Recommended platforms
- Pramp (pramp.com): Free peer-to-peer mock interviews, simulate real conditions
- interviewing.io: Anonymous practice với engineers từ Google/Meta/Amazon
- LeetCode Premium: Company-specific question lists (Google, Meta, Amazon, etc.)
- NeetCode.io: Structured roadmap, video explanations tốt nhất hiện tại
System Design
Sau khi DSA solid, System Design là phần quyết định senior-level offers.
Vault tiếp theo: System-Design-Mastery
Topics cần cover:
- Scalability fundamentals (horizontal/vertical scaling, load balancing)
- Database design (SQL vs NoSQL, sharding, replication)
- Caching strategies (Redis, CDN, cache invalidation)
- Message queues (Kafka, RabbitMQ)
- Design classic systems: URL Shortener, Twitter Feed, Uber, Netflix
Timeline Recommendation
| Trình độ hiện tại | Mục tiêu | Timeline |
|---|---|---|
| Junior (< 2 năm) | Intern/Junior FAANG | 4-6 tháng intensive |
| Mid-level (2-4 năm) | L4/L5 Engineer | 2-3 tháng focused |
| Senior (4+ năm) | L5/L6 Engineer | 6-8 tuần + System Design |
Daily routine đề xuất:
- Sáng (45 phút): 1 LeetCode medium mới — focus vào tốc độ và pattern recognition
- Tối (30 phút): Review 2-3 problems đã làm hôm qua — spaced repetition
- Cuối tuần (2 giờ): 1 mock interview session đầy đủ theo format buổi 12-13
8. Final Words from Your Sensei
Lời kết từ một FAANG Senior Engineer
“Mục tiêu không phải là ghi nhớ 500 LeetCode solutions. Mục tiêu là xây dựng pattern recognition mạnh đến mức bạn có thể phân tách bất kỳ bài toán nào bạn chưa gặp thành các patterns bạn ĐÃ gặp.
Khi tôi ngồi phỏng vấn, tôi không nghĩ ‘bài này tôi đã làm rồi’. Tôi nghĩ: ‘bài này hỏi về tối ưu trên một chuỗi con — sliding window. Có duplicate — cần HashMap. Minimize — co window khi hợp lệ. Xong, bắt đầu code.’
Đây là mindset bạn cần phát triển. Và nó không đến từ việc đọc solutions — nó đến từ hàng trăm giờ ngồi bí, vắt óc suy nghĩ, rồi đột nhiên thấy pattern.
Bạn đã đi qua toàn bộ vault này. Bạn đã đặt nền móng. Bây giờ nhiệm vụ duy nhất là lặp đi lặp lại cho đến khi nó trở thành bản năng.
Không có shortcut. Nhưng có con đường — và bạn đang đi đúng hướng.
Chúc mừng bạn đã hoàn thành DSA Mastery. Bây giờ, hãy ra ngoài và chứng minh nó.”
— A Senior Engineer who was once exactly where you are now
Bạn đã hoàn thành DSA Mastery Vault!
Đây không phải là kết thúc — đây là bắt đầu của giai đoạn thực chiến. Pattern recognition bạn đã xây dựng sẽ theo bạn suốt sự nghiệp, không chỉ qua được phỏng vấn FAANG.
Hành động tiếp theo ngay bây giờ:
- Tính Interview Readiness Score của bạn ở Section 6
- Chọn 3 weak topics để tập trung trong 2 tuần tới
- Đặt lịch mock interview đầu tiên trên Pramp hoặc interviewing.io
Navigation — Vault Links
- Buổi trước: 12-Practice-FAANG-1
- Toàn bộ roadmap: Roadmap-FAANG
- System Design vault: MOC-System-Design
- Tất cả patterns: All-Patterns-Cheatsheet