Problem-Solving Framework & Approach

0/12 in this phase0/57 across the roadmap

šŸ“– Concept

Having a systematic approach to solving problems is MORE important than knowing every algorithm. Top engineers and competitive programmers follow a framework — not random guessing.

The UMPIRE Method (Interview Framework):

  1. Understand the problem — Read carefully. Ask clarifying questions. What are the inputs? Outputs? Constraints?
  2. Match to known patterns — Is this a sliding window? Two pointers? DP? Graph problem?
  3. Plan your approach — Write pseudocode. Discuss time/space complexity BEFORE coding.
  4. Implement — Write clean, modular code. Use helper functions.
  5. Review — Walk through with an example. Check edge cases.
  6. Evaluate — Analyze complexity. Can you optimize?

Pattern Recognition — The Key Skill:

  • "Find subarray with property X" → Sliding window or prefix sum
  • "Find pair with property X" → Two pointers (sorted) or hash map
  • "Find optimal/count/can you" → Dynamic programming
  • "Generate all possibilities" → Backtracking
  • "Connected components" → Graph BFS/DFS or Union-Find
  • "Sorted data, find target" → Binary search
  • "Top K elements" → Heap
  • "String prefix matching" → Trie

Constraint-based complexity selection:

  • n ≤ 10: O(n!) — brute force, permutations OK
  • n ≤ 20: O(2ⁿ) — bitmask DP, subsets
  • n ≤ 500: O(n³) — 3 nested loops OK
  • n ≤ 5,000: O(n²) — 2 nested loops OK
  • n ≤ 10⁶: O(n log n) — sorting OK, but not O(n²)
  • n ≤ 10⁸: O(n) — single pass required
  • n > 10⁸: O(log n) or O(1) — binary search or math

šŸ  Real-world analogy: A doctor doesn't randomly prescribe medicine. They: 1) Listen to symptoms (understand), 2) Match to known conditions (pattern), 3) Decide treatment (plan), 4) Prescribe/operate (implement), 5) Follow up (review). Same process.

šŸ’» Code Example

codeTap to expand ā›¶
1// EXAMPLE: Solve "Two Sum" using the framework
2
3// Step 1: UNDERSTAND
4// Given: array of numbers, target sum
5// Find: indices of two numbers that add to target
6// Constraints: exactly one solution, can't use same element twice
7
8// Step 2: MATCH PATTERN
9// "Find pair" → hash map (store complement)
10
11// Step 3: PLAN
12// For each number, check if (target - number) exists in map
13// If yes → return both indices
14// If no → add current number to map
15
16// Step 4: IMPLEMENT
17function twoSum(nums: number[], target: number): [number, number] {
18 const map = new Map<number, number>(); // value → index
19
20 for (let i = 0; i < nums.length; i++) {
21 const complement = target - nums[i];
22 if (map.has(complement)) {
23 return [map.get(complement)!, i];
24 }
25 map.set(nums[i], i);
26 }
27
28 throw new Error("No solution found");
29}
30
31// Step 5: REVIEW — trace with example
32// nums = [2, 7, 11, 15], target = 9
33// i=0: complement=7, map={}, add 2→0, map={2:0}
34// i=1: complement=2, map={2:0} — FOUND! return [0, 1] āœ“
35
36// Step 6: EVALUATE
37// Time: O(n) — single pass
38// Space: O(n) — hash map
39// Better than O(n²) brute force!
40
41// CONSTRAINT-BASED APPROACH EXAMPLE
42function solveProblem(n: number): string {
43 if (n <= 20) return "Can use O(2^n) — bitmask/subset DP";
44 if (n <= 500) return "Can use O(n³) — 3 nested loops";
45 if (n <= 5000) return "Can use O(n²) — 2 nested loops";
46 if (n <= 1e6) return "Need O(n log n) — sorting-based";
47 if (n <= 1e8) return "Need O(n) — single pass";
48 return "Need O(log n) or O(1) — binary search or math";
49}
50
51// PATTERN MATCHING EXAMPLES
52// "Maximum subarray sum" → Kadane's algorithm (DP)
53function maxSubarraySum(arr: number[]): number {
54 let maxSoFar = arr[0];
55 let maxEndingHere = arr[0];
56 for (let i = 1; i < arr.length; i++) {
57 maxEndingHere = Math.max(arr[i], maxEndingHere + arr[i]);
58 maxSoFar = Math.max(maxSoFar, maxEndingHere);
59 }
60 return maxSoFar;
61}
62
63// "Find if path exists" → BFS/DFS
64function hasPath(graph: Map<number, number[]>, start: number, end: number): boolean {
65 const visited = new Set<number>();
66 const queue = [start];
67 while (queue.length) {
68 const node = queue.shift()!;
69 if (node === end) return true;
70 if (visited.has(node)) continue;
71 visited.add(node);
72 for (const neighbor of graph.get(node) || []) {
73 queue.push(neighbor);
74 }
75 }
76 return false;
77}

šŸ‹ļø Practice Exercise

Practice Problems:

  1. Using UMPIRE, solve: "Find the longest substring without repeating characters"
  2. Given n = 10,000, what's the maximum acceptable time complexity?
  3. Match each problem to a pattern:
    • "Find shortest path in unweighted graph" → ?
    • "Find maximum sum subarray" → ?
    • "Check if string matches pattern" → ?
  4. Walk through solving "Valid Parentheses" step-by-step with the framework
  5. Given constraint n ≤ 10⁵, would O(n²) solution pass? (assume 10⁸ ops/sec)
  6. Practice explaining your approach BEFORE writing code for 3 problems
  7. Solve a problem you've never seen — document your thinking process
  8. Take a brute force O(n³) solution and optimize it step by step to O(n)
  9. For a problem with multiple possible approaches, compare trade-offs
  10. Simulate a 45-min interview: 5 min understand, 10 min plan, 20 min code, 10 min review

āš ļø Common Mistakes

  • Jumping into coding without understanding the problem — you WILL solve the wrong problem

  • Not asking clarifying questions in interviews — interviewers EXPECT you to ask about edge cases, constraints, and assumptions

  • Trying to find the optimal solution immediately — start with brute force, then optimize

  • Not considering constraints to determine acceptable complexity — n ≤ 1000 means O(n²) is fine

  • Memorizing solutions instead of understanding patterns — you'll fail on any variation you haven't seen

šŸ’¼ Interview Questions

šŸŽ¤ Mock Interview

Practice a live interview for Problem-Solving Framework & Approach