Why a plan beats grinding
Most people prepare for coding interviews by opening a problem site and solving whatever shows up next. That feels productive but it is slow, because you keep relearning the same patterns and skipping the ones you find uncomfortable. A structured plan fixes the order, forces you to face your weak topics, and gives you a way to tell whether you are actually improving rather than just accumulating solved problems.
The plan below assumes you can already write a function and read your chosen language fluently. It runs for eight weeks at roughly one to two focused hours a day. If you have less time, stretch it out rather than cramming, because spaced practice sticks far better than a panicked sprint the week before the loop.
Pick one language and one place to track work
Before week one, make two decisions. Choose a single language and stick with it. Switching languages mid-prep wastes effort on syntax instead of patterns. Most people use Python for the terse syntax, but a language you already know well is usually the better pick.
Then set up a simple log. A spreadsheet with the problem, the pattern, whether you solved it unaided, and a one line note on what tripped you up is enough. This log is what turns practice into a feedback loop. Without it you cannot see which patterns still need work.
Weeks one and two, arrays, strings, and hashing
Start with the foundations because they appear inside almost every harder problem. Cover arrays, strings, the two pointer technique, sliding window, and hash maps for lookups and counting.
The recognition skill matters more than the code. When you read "find a pair that sums to a target," you want the hash map approach to come to mind immediately.
def two_sum(nums, target):
seen = {}
for i, n in enumerate(nums):
if target - n in seen:
return [seen[target - n], i]
seen[n] = i
return None
Aim for around twenty problems across these two weeks. After each, write down the pattern, not just whether you got it right. By the end you should recognise two pointer and sliding window problems within the first minute of reading.
Weeks three and four, stacks, queues, linked lists, and trees
Move to the linear and hierarchical structures. Cover stacks for matching and parsing, queues, linked list manipulation, and binary tree traversals both recursive and iterative.
Trees are where breadth-first and depth-first search become essential. Practise both until the templates are automatic, because half of the harder questions reduce to a traversal.
def level_order(root):
if not root:
return []
out, queue = [], [root]
while queue:
level = []
for _ in range(len(queue)):
node = queue.pop(0)
level.append(node.val)
if node.left: queue.append(node.left)
if node.right: queue.append(node.right)
out.append(level)
return out
Keep tracking which problems you needed a hint on. Those are the ones to revisit in week eight.
Weeks five and six, graphs and binary search
Graphs intimidate people, but most interview graph problems are just BFS or DFS on a structure you build from the input, such as a grid or an adjacency list. Cover connected components, shortest path in an unweighted graph, cycle detection, and topological sort.
Binary search deserves real attention because the hard version is not searching a sorted array. It is binary search on the answer: if you can write a check that says whether a candidate value is feasible, and feasibility is monotonic, you can search the space of answers.
This is also the point to get comfortable reasoning about time and space complexity out loud. Interviewers expect you to state the complexity before you code, so practise saying it for every problem you solve.
Weeks seven and eight, dynamic programming and review
Dynamic programming is the topic people fear most, so leave it until your foundations are solid. The core idea is simple: the answer is built from answers to smaller versions of the same problem, and you store those to avoid recomputing. Start by writing the plain recursion, then add memoisation, then convert to a table if time allows.
def coin_change(coins, amount):
dp = [0] + [float("inf")] * amount
for a in range(1, amount + 1):
for c in coins:
if c <= a:
dp[a] = min(dp[a], dp[a - c] + 1)
return dp[amount] if dp[amount] != float("inf") else -1
Spend the final week on review, not new material. Pull every problem from your log that you needed a hint on and redo it from scratch. This is the highest value work in the whole plan, because it converts shaky topics into solid ones right before the interview.
How to practise each problem
The way you practise matters as much as the volume. For each problem, give yourself a fixed time, say thirty minutes, to solve it unaided. If you are stuck after that, read the approach, then close it and implement the solution yourself without copying. The next day, redo any problem you needed help with.
Talk through your approach out loud as if an interviewer were present. State the pattern, the approach, and the complexity before writing code. This builds the habit you will need in the room, where silent coding reads as a weakness even when the answer is correct.
Avoiding the common traps
- Chasing problem count. Fifty problems understood deeply beat three hundred solved once and forgotten.
- Skipping your weak topics because they are uncomfortable. Those are exactly the ones the interviewer will find.
- Memorising solutions instead of patterns. New questions will not match what you memorised.
- Practising only in silence. The interview is a spoken exercise, so rehearse it that way.
Follow the plan, keep the log honest, and review your weak spots at the end. Eight weeks of focused, pattern-led practice will leave most new questions feeling familiar within the first minute, which is the calm you want when it counts.
Continue your prep
Apply the plan against real role questions and patterns: