06 — Problem-Solving Strategy¶
By this point in the phase you know the patterns — arrays, trees, graphs, DP. What separates people who pass studies from people who fail them is not knowing more patterns; it is executing a repeatable process under time pressure while thinking out loud. This file gives you that process, a pattern-recognition table you can run in your head in under two minutes, and a 25-minute time budget you can enforce with a timer.
The 5-step approach (never skip a step)¶
Every good study partner expects you to run some version of this. If you skip step 1 or 2 and dive into code, you look like a junior. If you skip step 3, you often overengineer.
Step 1 — Clarify (2 min)¶
Ask questions before you touch the keyboard. Aim for 3-5 questions minimum.
Input constraints — size, range, can be negative, can be empty, can be null, sorted, unique?
Output format — return the value, or the index? All answers, or just one? Any valid answer, or the lexicographically smallest?
Edge cases — empty input, single element, all identical, all negative, integer overflow risk?
Constraints — does the array fit in memory? Are we optimizing for time, space, or readability?
Write the constraints on the whiteboard/screen as you learn them. This is not just for the study partner — you will forget them mid-code and re-ask, which looks bad.
Step 2 — Examples (2 min)¶
Work through the given example by hand. Then invent two more: one trivial (empty or size 1) and one tricky (duplicates, negatives, boundary). study partners reward candidates who catch bugs in their own examples before coding.
Step 3 — Brute force (2 min)¶
State the brute force even if you already see the optimal solution. Two sentences: what it does, what its complexity is. “I could nested-loop this for O(n²) and O(1) space. Let me see if I can do better.” This shows the study partner you understand the trade-off, and it gives you a fallback if the optimal solution stalls.
Step 4 — Optimize (4 min)¶
Look for the pattern signature (table below). State the optimization out loud: “Since the array is sorted, I can use two pointers instead of nested loops.” Get the study partner’s nod before coding. If they push back, they are hinting.
Step 5 — Code, test, discuss (13 min + 2 min)¶
Code it. Talk through what you are typing. When done, walk through your own trivial and tricky examples — don’t wait to be asked. Mention complexity and one thing you would improve if you had more time.
Pattern signature table¶
Run this table top-to-bottom in your head while reading the problem. Stop at the first match. This is how you “see” the solution in 90 seconds.
You see … |
Reach for … |
Why |
|---|---|---|
“find duplicates / has X been seen” |
|
O(1) lookup, O(n) time |
“array is sorted + find pair / target” |
Two pointers (opposite ends) |
Sorted structure enables monotone motion |
“sorted + find one value” |
Binary search |
O(log n), don’t waste it |
“top K / K-th largest / K-th smallest” |
|
O(n log K) |
“median of a stream” |
Two heaps (max-heap + min-heap) |
Balance them by size |
“contiguous subarray / substring, fixed or variable window” |
Sliding window |
Amortized O(n) |
“subarray sum equals K” |
Prefix sum + |
Turns a range query into O(1) lookup |
“any subsequence / subset / partition into groups” |
DP or backtracking |
Choice at each step |
“count number of ways” |
DP (combinatorial) |
Overlapping subproblems |
“max/min under a constraint” |
DP (optimization) or greedy |
Prove greedy or fall back to DP |
“shortest path in unweighted graph” |
BFS |
Layered = shortest by edge count |
“shortest path with non-negative weights” |
Dijkstra + |
Greedy with priority |
“detect cycle in undirected graph” |
DFS parent tracking / Union-Find |
Two proven approaches |
“detect cycle in directed graph” |
DFS with 3 colors (white/gray/black) |
Gray-hit = back edge |
“dependency order / prerequisites” |
Topological sort (Kahn’s or DFS post-order) |
DAG shape |
“connected components / groups / equivalence” |
Union-Find (DSU) |
Near O(n α(n)) |
“tree — root-to-node / bottom-up aggregation” |
DFS (recursive) |
Natural recursion |
“tree — level by level” |
BFS with size snapshot |
Track level boundary |
“tree with ‘k-th’ or ‘range’ queries” |
In-order traversal or Fenwick/Segment tree |
Ordered access |
“palindrome / matching brackets” |
Two pointers or |
Structural mirror |
“next greater / smaller element” |
Monotonic stack |
O(n) via amortized pushes |
“prefix strings / autocomplete” |
Trie |
Shared prefixes = shared nodes |
“schedule / merge / intervals” |
Sort by start, then linear scan |
O(n log n) |
“reservoir / random from stream” |
Reservoir sampling |
O(1) space, O(n) time |
“cycle detection / start of cycle in a linked list” |
Floyd’s tortoise and hare |
O(1) space |
“reverse in-place” |
Two pointers or three-pointer LL trick |
O(1) space |
⚠️ What most people get wrong: they memorize this table and try to force-fit a pattern before understanding the constraints. If the array size is 20, you don’t need O(n log n) — backtracking is fine. Pattern matching is a shortlist, not a decision.
25-minute study time budget¶
This is what you should be spending time on in a 45-minute technical screen (assume 5 min small talk + 15 min follow-up questions/behavioral).
Phase |
Time |
You are doing |
|---|---|---|
Clarify |
2 min |
Asking questions, writing constraints on the board |
Examples |
2 min |
Two additional examples (trivial + tricky) |
Brute force |
2 min |
State it, complexity it, don’t code it |
Optimize |
4 min |
Name the pattern, sketch the approach, get the nod |
Code |
10 min |
Write clean Java, talk while typing |
Test |
3 min |
Walk through your own examples, off-by-one hunt |
Discuss |
2 min |
Complexity, alternatives, what you’d improve |
If you are 15 minutes in and have not written a single line of Java, you are late. Drop back to the brute force and code that — a working brute force with clear reasoning beats an unfinished optimal solution every time.
Talk-out-loud discipline¶
study partners cannot read your mind, and silent candidates get downgraded even when their code works. Some phrases to bank:
“Let me think about this out loud for a minute.”
“One approach is X, which gives us O(n²). Let me see if we can do better.”
“If the input is sorted / has this property, I can …”
“I’m going to use a HashMap to trade space for time here.”
“Let me trace through the trivial case first: empty array → return 0.”
“I notice I have an off-by-one. Let me fix that.” (much better than fixing silently)
“If I had more time, I’d …” (end on a strong note)
⚠️ What most people get wrong: they narrate the what (“I’m writing a for loop”) instead of the why (“I need to check every pair, so I nest a loop”). Narrate reasoning, not syntax.
Common failure modes (and the fix)¶
Failure |
Fix |
|---|---|
Jumps to code, has to rewrite twice |
Force 4 min of clarify + brute before coding |
Silent for 5 minutes staring at the problem |
Say “let me restate the problem” and read it aloud |
Writes optimal solution, has 3 bugs, can’t finish |
Ship the brute force first, then optimize if time |
Gets O(n²), doesn’t know the O(n) trick |
Say what you’d try: “I suspect there’s a hash-map trick here” |
Panics on off-by-one |
Trace 3 small examples on paper before submitting |
Ignores study partner hints |
Repeat their hint back: “You mentioned sorted — does that mean binary search?” |
Doesn’t test the code |
Always dry-run the trivial and tricky examples |
Java-specific execution tips¶
These are the little things that make your code look senior in Java specifically.
Use
varfor locals when the RHS makes the type obvious (var seen = new HashMap<Integer,Integer>()).Prefer
List.of(…)for constant test inputs; notArrays.asList(fixed-size, backed by array).Use
Map.getOrDefault(k, 0)instead of null-checking a get.Use
map.merge(k, 1, Integer::sum)for frequency counting — one line, no ternary.Use
Integer.compare(a, b)in comparators, nevera - b(overflow bug).Return
Collections.emptyList()/List.of()for empty results, nevernull.If iterating and mutating a collection, use
Iterator.remove()orCollection.removeIf.For string building in a loop,
StringBuilder. For a few concats outside a loop,+is fine — the compiler makes aStringBuilderfor you.int[] arrfor hot inner loops. Autoboxing toInteger[]costs you 20-40% in study time-limit territory.
Weekly practice rhythm (weeks 8-9 of Phase 02)¶
By the end of this phase, aim for this weekly cadence, timed with a real 25-minute clock:
Day |
Session |
Target |
|---|---|---|
Mon |
2 mediums, timed 25 min each |
1 solve, 1 acceptable partial |
Tue |
1 hard, untimed |
Fully understand + write up |
Wed |
Rest / review the write-ups |
|
Thu |
2 mediums, timed 25 min each |
2 solves |
Fri |
1 hard, timed 45 min |
Solve or fail cleanly |
Sat |
Mock study (Pramp / friend / rubber duck) |
Full 45-min run |
Sun |
Blog / write up the week |
Consolidation |
⚠️ What most people get wrong: they do 200 problems untimed and 0 timed. LeetCode without a timer is reading, not training. The clock is the study partner.
Exit self-check¶
Before you leave Phase 02, you should be able to say “yes” to all of these:
Given any of the 25 problems in the pattern-signature table, you can name the pattern in under 30 seconds.
You can code the 5-step process in a mock without looking at notes.
You have solved and pattern-tagged 150+ problems in your public repo.
You have failed at least 10 timed mocks and analyzed each failure. (Failure count matters more than success count at this stage.)
If any “no,” don’t advance yet — the next phase (systems + Spring) assumes this fluency, and rebuilding it later costs 3× the time.
Return to README.md · Next: projects.md