Pattern Recognition & Problem-Solving Strategy

📖 Concept

Pattern recognition is the meta-skill that separates senior engineers from those who just memorize solutions. Instead of solving each problem from scratch, you match it to a known pattern.

Core patterns and their triggers:

1. Sliding Window — Subarray/substring with condition

  • Trigger: "contiguous subarray", "substring", "window of size K"
  • Template: Two pointers (left, right) expanding right, shrinking left

2. Two Pointers — Sorted array, pair finding

  • Trigger: "sorted array", "pair that sums to", "in-place"
  • Template: left=0, right=end, move based on comparison

3. BFS — Shortest path, level-order

  • Trigger: "shortest", "minimum steps", "level by level", "unweighted graph"
  • Template: Queue + visited set

4. DFS / Backtracking — All combinations, permutations

  • Trigger: "all possible", "generate all", "combinations", "subsets"
  • Template: Recursive with state, undo state on backtrack

5. Dynamic Programming — Optimal substructure + overlapping subproblems

  • Trigger: "minimum/maximum", "number of ways", "can you reach"
  • Template: Define state, recurrence relation, base case

6. Binary Search — Sorted data, search space reduction

  • Trigger: "sorted", "minimum that satisfies", "search space"
  • Template: lo, hi, mid, adjust based on condition

7. Monotonic Stack — Next greater/smaller element

  • Trigger: "next greater", "stock span", "histogram"
  • Template: Stack of indices, pop when current > top

8. Union-Find — Connected components, grouping

  • Trigger: "connected", "components", "cycle in undirected graph"
  • Template: parent array, find with path compression, union by rank

💻 Code Example

codeTap to expand ⛶
1// Pattern matching examples
2
3// PATTERN: When you see "subarray with sum = K" → Prefix sum + HashMap
4fun subarraySum(nums: IntArray, k: Int): Int {
5 val prefixCount = mutableMapOf(0 to 1) // prefix_sum → count
6 var sum = 0
7 var count = 0
8 for (num in nums) {
9 sum += num
10 count += prefixCount.getOrDefault(sum - k, 0)
11 prefixCount[sum] = prefixCount.getOrDefault(sum, 0) + 1
12 }
13 return count
14}
15// Trigger identified: "subarray" + "sum equals K"
16// Pattern: Prefix sum with HashMap
17
18// PATTERN: When you see "generate all subsets" → Backtracking
19fun subsets(nums: IntArray): List<List<Int>> {
20 val result = mutableListOf<List<Int>>()
21
22 fun backtrack(start: Int, current: MutableList<Int>) {
23 result.add(current.toList()) // Add current subset
24 for (i in start until nums.size) {
25 current.add(nums[i]) // Choose
26 backtrack(i + 1, current) // Explore
27 current.removeAt(current.lastIndex) // Un-choose
28 }
29 }
30
31 backtrack(0, mutableListOf())
32 return result
33}
34
35// PATTERN: When you see "K-th largest" → Min-heap of size K
36fun findKthLargest(nums: IntArray, k: Int): Int {
37 val minHeap = PriorityQueue<Int>() // Min-heap
38 for (num in nums) {
39 minHeap.offer(num)
40 if (minHeap.size > k) minHeap.poll() // Remove smallest
41 }
42 return minHeap.peek() // K-th largest is at top
43}
44// O(n log k) time, O(k) space
45
46// PATTERN: When you see "minimum in rotated sorted" → Modified binary search
47fun findMin(nums: IntArray): Int {
48 var lo = 0
49 var hi = nums.lastIndex
50 while (lo < hi) {
51 val mid = lo + (hi - lo) / 2
52 if (nums[mid] > nums[hi]) lo = mid + 1
53 else hi = mid
54 }
55 return nums[lo]
56}

🏋️ Practice Exercise

Pattern Recognition Drill: For each problem, identify the pattern BEFORE solving:

  1. "Find all anagrams in a string" → ? (Sliding window + frequency map)
  2. "Minimum number of jumps to reach end" → ? (Greedy / BFS)
  3. "Clone a graph" → ? (BFS + HashMap)
  4. "Coin change — minimum coins" → ? (DP — bottom-up)
  5. "Find celebrity in a party" → ? (Two pointers / elimination)
  6. "Merge K sorted lists" → ? (Min-heap)
  7. "Longest palindromic substring" → ? (Expand around center / DP)
  8. "Number of islands" → ? (BFS/DFS grid traversal)
  9. "Decode ways" → ? (Linear DP — fibonacci variant)
  10. "Task scheduler with cooldown" → ? (Greedy + math / max-heap)

⚠️ Common Mistakes

  • Memorizing solutions without understanding the pattern — different inputs will break your memorized approach

  • Forcing a pattern that doesn't fit — if two pointers doesn't work, consider sliding window or hashmap

  • Not recognizing DP problems — the triggers are 'optimal' (min/max), 'count ways', and overlapping subproblems

  • Using DFS when BFS is needed — BFS guarantees shortest path in unweighted graphs, DFS does not

💼 Interview Questions

🎤 Mock Interview

Mock interview is powered by AI for Pattern Recognition & Problem-Solving Strategy. Login to unlock this feature.