Study Plan, Templates and Mock Interview Playbook
This last chapter turns the material into a routine. It gives a study plan you can adapt to the time you have, a one-page template sheet to rebuild from memory, a table for recognising problems, and a playbook for the final week and the interview itself.
1. How to use your time
Most people prepare badly in one of two ways: they read solutions without struggling first, or they grind hundreds of problems without ever revisiting a mistake. What builds skill is attempt, struggle, check, then redo from memory after a gap.
A reliable loop for each problem:
- Attempt for 20 to 30 minutes with no hints. Say your reasoning aloud or write it down.
- If stuck, read only the pattern name or the first hint, then try again for 10 minutes.
- Read a full solution. Compare it with yours and note the insight you missed, in one sentence.
- Redo the problem from scratch after 2 days, then after 7 days, without looking.
- Keep a mistake log: the problem, the pattern, the insight, the bug you made.
Aim for fewer problems, understood deeply. Sixty to ninety well-reviewed problems across all patterns beat three hundred skimmed ones.
2. A plan by time available
| Time | Focus |
|---|---|
| 2 weeks | Arrays and hashing, two pointers and windows, stacks, binary search, trees, BFS and DFS, basic DP. Skip tries, segment trees and bit tricks unless the role needs them. 3 problems a day plus review. |
| 6 weeks | All patterns once in order, then a second pass over the ones you got wrong. Add two mock interviews a week from week 4. |
| 12 weeks | Everything, plus hard problems, a full second pass, system design basics if the role needs them, and weekly timed mocks. |
A six-week sketch:
| Week | Topics | Output |
|---|---|---|
| 1 | Complexity, arrays and hashing, two pointers, sliding window | 15 problems, mistake log started |
| 2 | Stacks, queues, binary search, linked lists | 15 problems |
| 3 | Trees, BST, heaps, sorting and intervals | 15 problems, one mock |
| 4 | Graphs (BFS, DFS, grids, topological sort, union-find), shortest paths | 12 problems, two mocks |
| 5 | Recursion and backtracking, dynamic programming (1D then 2D) | 15 problems, two mocks |
| 6 | Greedy, tries, design problems, revisit the mistake log, timed mocks | Weak topics redone, two or three mocks |
3. The one-page template sheet
If you can write each of these from memory in a minute, you have the patterns.
Binary search on a sorted array (first index where condition is true):
def first_true(lo, hi, ok): # ok is monotone: False ... False True ... True
while lo < hi:
mid = (lo + hi) // 2
if ok(mid):
hi = mid
else:
lo = mid + 1
return lo
assert first_true(0, 10, lambda x: x * x >= 50) == 8
Sliding window (longest substring satisfying a condition):
def longest_window(s, max_distinct):
counts, left, best = {}, 0, 0
for right, ch in enumerate(s):
counts[ch] = counts.get(ch, 0) + 1
while len(counts) > max_distinct: # shrink until valid again
counts[s[left]] -= 1
if counts[s[left]] == 0:
del counts[s[left]]
left += 1
best = max(best, right - left + 1)
return best
assert longest_window("eceba", 2) == 3
BFS on a graph (shortest path in steps):
from collections import deque
def bfs_distance(graph, start, goal):
seen, queue = {start}, deque([(start, 0)])
while queue:
node, d = queue.popleft()
if node == goal:
return d
for nxt in graph[node]:
if nxt not in seen:
seen.add(nxt)
queue.append((nxt, d + 1))
return -1
g = {"a": ["b", "c"], "b": ["d"], "c": ["d"], "d": []}
assert bfs_distance(g, "a", "d") == 2 and bfs_distance(g, "d", "a") == -1
Backtracking (all subsets):
def subsets(nums):
result, path = [], []
def go(i):
if i == len(nums):
result.append(path[:])
return
go(i + 1) # skip nums[i]
path.append(nums[i]); go(i + 1); path.pop() # take nums[i]
go(0)
return result
assert sorted(map(tuple, subsets([1, 2, 3]))) == sorted([(), (1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)])
Dynamic programming (1D, state is the index):
def house_robber(nums):
take, skip = 0, 0
for x in nums:
take, skip = skip + x, max(take, skip)
return max(take, skip)
assert house_robber([2, 7, 9, 3, 1]) == 12
Monotonic stack (next greater element):
def next_greater(nums):
result, stack = [-1] * len(nums), []
for i, x in enumerate(nums):
while stack and nums[stack[-1]] < x:
result[stack.pop()] = x
stack.append(i)
return result
assert next_greater([2, 1, 2, 4, 3]) == [4, 2, 4, -1, -1]
Heap, top k frequent:
import heapq
from collections import Counter
def top_k_frequent(nums, k):
return [x for x, _ in heapq.nlargest(k, Counter(nums).items(), key=lambda p: p[1])]
assert set(top_k_frequent([1, 1, 1, 2, 2, 3], 2)) == {1, 2}
4. Recognising the pattern
| Phrase in the problem | First thing to try |
|---|---|
| "Sorted array", "find in logarithmic time" | Binary search |
| "Contiguous subarray or substring with a property" | Sliding window, or prefix sums with a hash map |
| "Pair or triple that sums to ..." | Sort and two pointers, or hash set |
| "Next greater or smaller", "span", "histogram" | Monotonic stack |
| "Top k", "k-th largest", "merge k lists" | Heap |
| "Shortest path, fewest steps" (unweighted) | BFS |
| "Shortest path with weights" | Dijkstra (non-negative), Bellman-Ford otherwise |
| "Connected components, are these connected, dynamic merges" | Union-find |
| "Order with dependencies", "prerequisites" | Topological sort |
| "All combinations, permutations, subsets", "place under constraints" | Backtracking |
| "Minimum or maximum, count ways, can you reach" with overlapping subproblems | Dynamic programming |
| "Intervals", "meetings", "schedule" | Sort, then sweep or greedy |
| "Prefix of strings", "autocomplete", "word search" | Trie |
| "Design a structure with operations" | Hash map plus linked list or array |
| "Subarray sum equals k" including negatives | Prefix sum with hash map |
| "Single number, powers of two, subsets as masks" | Bit manipulation |
5. Complexity quick reference
| Operation | Typical cost |
|---|---|
| Hash map or set lookup, insert | average |
| Sort | |
| Heap push, pop | |
| Binary search | |
| BFS or DFS on a graph | |
| Dijkstra with a heap | |
| Subsets of items | |
| Permutations of items | |
| 2D DP over two strings of lengths and |
If your constraint is , think exponential (subsets, bitmask). If , you need or better. If , is fine.
6. The final week
- Stop learning new patterns two or three days before. Revise the mistake log and redo problems you missed.
- Do timed, spoken mocks, ideally with another person, in a plain editor without autocomplete.
- Rehearse your opening: restate the problem, ask two clarifying questions, give examples, propose brute force, then improve.
- Sleep. Tired candidates make off-by-one errors that rested ones do not.
- Prepare your environment: stable connection, charged laptop, a pen and paper, water, and a tested video setup.
7. Mock interview playbook
During a 45-minute round:
| Minutes | What to do |
|---|---|
| 0 to 5 | Restate the problem. Ask about input size, duplicates, negative numbers, empty input, whether the data is sorted. Write a small example and its answer. |
| 5 to 10 | State a brute force and its complexity. Find the bottleneck. Propose the better approach and ask whether the interviewer agrees before coding. |
| 10 to 30 | Code cleanly, with meaningful names. Narrate key decisions. Avoid silent stretches. |
| 30 to 40 | Trace a test case by hand. Then test the edges: empty, single element, duplicates, the largest case. Fix bugs calmly. |
| 40 to 45 | State time and space complexity. Mention possible improvements. Leave time for questions. |
If you are stuck: say what you have tried and what is blocking you. Interviewers want to see how you recover. Try a smaller example, a brute force, or ask what property of the input you may be missing. Taking a hint is normal and costs less than silence.
If you find a bug late: say so, locate it, fix it. Do not defend broken code.
If you have seen the problem before: say so honestly and still walk through your reasoning. Pretending to discover a memorised solution usually shows.
8. Questions to ask your interviewer
At the end, ask things you want to know: what the team is building now, how engineers are onboarded, how the team handles code review, and what a strong first six months looks like. Avoid questions you could answer from a website, and avoid asking about compensation at this stage unless the recruiter opens it.
9. Common mistakes in preparation
- Reading solutions too early, which trains recognition, not recall.
- Never reviewing. Without spaced repetition, most of what you solved is gone in a month.
- Memorising solutions instead of patterns, which fails on variations.
- Skipping complexity analysis, which interviewers always ask about.
- Practising only in an IDE with autocomplete, then freezing in a plain editor.
- Not practising speaking. Thinking aloud is a skill, and it needs reps.
- Ignoring weak areas (usually graphs or DP) because they feel bad.
- Cramming the night before, which adds anxiety and little knowledge.
10. A closing checklist
- I can state the time and space complexity of every solution I write.
- I can write the templates in section 3 from memory.
- I ask clarifying questions and give examples before coding.
- I can explain why my solution is correct, not only what it does.
- I test with an empty input, a single element and a duplicate-heavy input.
- I keep a mistake log and revisit it every week.
- I have done at least five full mock interviews under time pressure.