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”

HashSet / HashMap

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”

PriorityQueue (min-heap of size K)

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 + HashMap<Integer,Integer>

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 + PriorityQueue

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 Stack

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 var for locals when the RHS makes the type obvious (var seen = new HashMap<Integer,Integer>()).

  • Prefer List.of(…) for constant test inputs; not Arrays.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, never a - b (overflow bug).

  • Return Collections.emptyList() / List.of() for empty results, never null.

  • If iterating and mutating a collection, use Iterator.remove() or Collection.removeIf.

  • For string building in a loop, StringBuilder. For a few concats outside a loop, + is fine — the compiler makes a StringBuilder for you.

  • int[] arr for hot inner loops. Autoboxing to Integer[] 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