Back to Blog

Coding Interview Patterns: How to Recognize and Solve Them

Published December 11, 2025
Updated October 4, 2026Technical Tips7 min read

By

Last updated October 4, 2026

Coding Interview Patterns: How to Recognize and Solve Them

Coding interviews reward pattern recognition and clear communication more than raw cleverness. Almost every problem you will see is a variation on a dozen patterns, and interviewers watch how you get from a vague prompt to working code as closely as they watch the code itself. This guide lists the patterns, the signals in a problem that point to each one, a study plan, and how to run the 45 minutes.

It replaces our separate short pages on arrays, hash tables, linked lists, trees, graphs, recursion, sorting, binary search and dynamic programming, because those topics are easier to learn together than apart.

How a coding interview is scored

Interviewers typically write notes on four things: whether you understood the problem, whether your approach was sound, whether your code worked and was clean, and how you communicated. Getting the optimal solution helps, but a candidate who clarifies the problem, proposes a reasonable approach, codes it cleanly and tests it often scores better than one who silently produces the optimal answer. Practice the whole loop, not only the algorithm.

Match the signal to the pattern

If the problem says...Try thisTypical cost
"find a pair / has duplicate / count occurrences"Hash map or setO(n) time, O(n) space
Sorted array, or a pair/triple that meets a conditionTwo pointersO(n) after sorting
Longest/shortest/max-sum contiguous subarray or substringSliding windowO(n)
Sorted input, or "minimum value that works"Binary search (on index or on the answer)O(log n)
Shortest path in an unweighted graph or grid, level by levelBFSO(V + E)
Explore all connected cells, paths, or componentsDFSO(V + E)
Tree questions (depth, path sum, validate BST)Recursion with a clear return valueO(n), O(h) stack
"All combinations / permutations / subsets"BacktrackingExponential; prune early
"Number of ways" or "min/max cost" with overlapping subproblemsDynamic programmingUsually O(n) to O(n*m)
"Top k", "kth largest", merge sorted streamsHeapO(n log k)
"Next greater element", matching bracketsStack (monotonic stack)O(n)
Overlapping ranges, meeting roomsSort by start, sweepO(n log n)
Linked list cycle, middle node, reverseFast/slow pointers; pointer reversalO(n), O(1) space

The patterns, with one example each

Hash map: remember what you have seen

The brute-force answer to "find two numbers that sum to a target" checks every pair, O(n²). A hash map lets you ask "have I already seen the number I need?" in constant time:

def two_sum(nums, target):
    seen = {}                      # value -> index
    for i, n in enumerate(nums):
        if target - n in seen:
            return [seen[target - n], i]
        seen[n] = i
    return []

Sliding window: contiguous ranges without recomputing

Longest substring without repeating characters. Grow the right edge; when a repeat appears, shrink the left edge until the window is valid again:

def longest_unique(s):
    last, left, best = {}, 0, 0
    for right, ch in enumerate(s):
        if ch in last and last[ch] >= left:
            left = last[ch] + 1
        last[ch] = right
        best = max(best, right - left + 1)
    return best

Binary search, including "search on the answer"

Beyond finding a value in a sorted array, binary search works whenever you can test a candidate answer and the result flips from false to true at some point. For example, "the minimum speed that finishes in time" tests a speed and moves left or right:

def first_true(lo, hi, ok):
    # smallest x in [lo, hi] where ok(x) is True, assuming ok is monotonic
    while lo < hi:
        mid = (lo + hi) // 2
        if ok(mid):
            hi = mid
        else:
            lo = mid + 1
    return lo

BFS and DFS: graphs and grids

Treat a grid as a graph. BFS finds the shortest path when every step costs the same; DFS is the natural fit for counting islands or checking connectivity. Mark nodes visited when you add them to the queue, not when you pop them, or you will enqueue duplicates:

from collections import deque

def shortest_path(grid, start, end):
    rows, cols = len(grid), len(grid[0])
    q, seen = deque([(start, 0)]), {start}
    while q:
        (r, c), dist = q.popleft()
        if (r, c) == end:
            return dist
        for dr, dc in ((1,0),(-1,0),(0,1),(0,-1)):
            nr, nc = r + dr, c + dc
            if 0 <= nr < rows and 0 <= nc < cols and grid[nr][nc] == 0 and (nr, nc) not in seen:
                seen.add((nr, nc))
                q.append(((nr, nc), dist + 1))
    return -1

Trees: decide what each call returns

Most tree bugs come from not deciding what the recursive function returns. For maximum depth the answer is one line once you decide it returns "the depth of this subtree":

def max_depth(node):
    if not node:
        return 0
    return 1 + max(max_depth(node.left), max_depth(node.right))

Backtracking: choose, explore, undo

def subsets(nums):
    out, path = [], []
    def go(i):
        if i == len(nums):
            out.append(path[:])
            return
        go(i + 1)                 # skip nums[i]
        path.append(nums[i])      # take nums[i]
        go(i + 1)
        path.pop()                # undo
    go(0)
    return out

Dynamic programming: name the state first

Do not start by writing a table. Say out loud: "the state is the best answer using the first i items", then "the choice at each step is X or Y", then write the recurrence. Climbing stairs (n steps, one or two at a time) is the smallest example:

def climb(n):
    a, b = 1, 1                   # ways to reach step 0 and 1
    for _ in range(n - 1):
        a, b = b, a + b
    return b

Start with a plain recursive solution, add memoization if subproblems repeat, and only then convert to a table if you need the speed.

Linked lists: two pointers and reversal

Draw the pointers on paper before coding. Reversing a list in place is the foundation for a surprising number of questions:

def reverse(head):
    prev = None
    while head:
        head.next, prev, head = prev, head, head.next
    return prev

Data structures you should be able to explain, not just use

  • Array / dynamic array: O(1) index, amortized O(1) append, O(n) insert in the middle.
  • Hash table: average O(1) lookup and insert, O(n) worst case with many collisions; keys must be hashable and order is not the point.
  • Heap: O(log n) push and pop, O(1) peek at the min or max.
  • Balanced BST / sorted structure: O(log n) ordered operations, useful when you need floor/ceiling or ranges.
  • Graph: adjacency list for sparse graphs, matrix for dense ones.

Interviewers love to ask "what is the trade-off?" Having this table in your head is the answer.

Running the 45 minutes

  1. Minutes 0-5: clarify. Restate the problem in your own words. Ask about input size, duplicates, empty input, negative numbers, and whether the input is sorted.
  2. Minutes 5-12: approach. Say the brute force and its cost, then the better idea and why. Get the interviewer to agree before you code.
  3. Minutes 12-35: code. Narrate as you type. Use clear variable names. If you get stuck, say what you are trying and what is not working.
  4. Minutes 35-42: test. Walk through one normal example and one edge case by hand. Catch your own bugs before the interviewer does.
  5. Minutes 42-45: wrap up. State time and space complexity, and mention one improvement you would make with more time.

A study plan that is not 400 problems

WeekFocusGoal
1Arrays, strings, hash maps, two pointersSolve easy-to-medium problems without hints
2Sliding window, binary search, stacksRecognize the signal in under a minute
3Trees, BFS/DFS, linked listsWrite recursion with a clear return value
4Backtracking, DP, heapsName the state and recurrence before coding
5+Timed mixed sets, mock interviews out loudFinish a medium in about 25 minutes and explain it

For each problem, after you solve it (or give up after 20-30 minutes), write down the pattern and the signal that revealed it. Reviewing the pattern list weekly beats grinding new problems. A mock interview where you have to talk through your solution out loud closes the gap between solving and explaining.

Common mistakes

  • Coding before agreeing on the approach. You lose ten minutes on the wrong idea.
  • Going silent when stuck. Interviewers can only credit and help with what they hear.
  • Skipping edge cases like empty input, a single element, and duplicates.
  • Memorizing solutions. A small change to the problem breaks a memorized answer; a pattern survives it.
  • Optimizing too early. A correct O(n²) answer you can improve is better than a broken O(n) attempt.

Frequently asked questions

How many LeetCode problems should I solve before interviews?

There is no magic number. A few dozen well-reviewed problems covering each pattern above, plus timed practice, does more than hundreds solved without reflection.

What is the best language for coding interviews?

The one you know best, unless the job requires a specific language. Python is popular because it is concise, but you should know your language's standard library for heaps, queues and hash maps.

What if I cannot solve the problem?

Say so, describe the brute force, and ask for a hint. A working suboptimal solution plus clear thinking usually scores better than an incomplete optimal attempt.

Can I use AI during a coding interview?

Only if the employer says it is allowed. Some do now, and many proctored assessments forbid it. Read our guide to the rules and how to use AI for coding practice.

Share:
#TechnicalTips#InterviewPrep#CareerGrowth