Cracking the Tech Interview

Cracking the Tech Interview

Master the 10 Top Coding Patterns for Coding Interviews in 2026

Most people prepare for coding interviews by collecting problems. Strong candidates prepare by mastering patterns. Here are the ten that cover the overwhelming majority of what you will face

Rafay Abbasi's avatar
Rafay Abbasi
Jul 25, 2026
∙ Paid

There are two ways to prepare for a coding interview.

The first is to collect problems. You study a solution, understand it, move to the next, and repeat until you have a catalog large enough to hope something in the interview looks familiar.

This approach has a ceiling: it only works when the new problem closely resembles one you have already seen.

Change the phrasing, add a twist, and the catalog fails.

The second is to master patterns.

You learn not the solutions but the underlying structures that produce them. You learn what makes a problem want a sliding window, not just how to solve the longest-substring problem.

You learn why a sorted input points toward two pointers, not just the specific code for pair-sum. That understanding transfers to every problem in the pattern’s family, including ones you have never seen, because you are not matching a template. You are reading evidence.

This guide covers the ten patterns that appear most often in coding interviews.

For each one you will get the core idea, the signals that identify it, at least one tested implementation, and the recognition tell that tells you in ninety seconds whether this pattern applies.

By the end you will have the vocabulary and the intuition for the problems that show up most, and more importantly you will understand why each pattern works, which is what lets you adapt it when the problem wears a different costume.

Here are the ten patterns explained from the ground up.

The Philosophy behind Pattern-based Preparation

Before the patterns, understand what you are building and why it beats the alternative.

When you grind problems individually, you are building a catalog.

The catalog has a fatal weakness: it only helps when the new problem closely resembles something you have already seen.

Change the phrasing, add a small twist, and the catalog fails. This is why candidates who have solved five hundred problems still freeze, and why interviewers deliberately disguise their problems so that pattern-matching breaks and only understanding survives.

When you internalize a pattern, you are building recognition. You learn what makes a problem want a sliding window, not just how to solve the longest-substring problem.

You learn why a sorted input points toward two pointers, not just the specific code for pair-sum. That understanding transfers to every problem in the family, including ones you have never seen, because you are not matching a template, you are reading evidence.

Ten patterns cover the vast majority of coding interview problems. That is the practical payoff of this approach: a small number of understood structures handles an enormous range of problems. Here they are.

Pattern 1: Sliding Window

A sliding window is a contiguous subarray or substring that you optimize over.

Instead of re-examining every possible subarray from scratch (which is O(n squared)), you maintain a window that expands and contracts as it slides across the data, updating its properties incrementally. Each element enters the window exactly once and leaves at most once, keeping the whole thing O(n).

The recognition signal. The words “contiguous subarray,” “substring,” or “consecutive elements” paired with a longest, shortest, maximum, or minimum. If the problem asks about a continuous run of elements and you are optimizing over those runs, reach for a sliding window before anything else.

Two variants to know

The fixed-size window is the simpler one. The window size is given (K elements), and you slide it one step at a time, adding the entering element and subtracting the leaving one:

python

def max_sum_k(nums, k):
    window = sum(nums[:k])
    best = window
    for i in range(k, len(nums)):
        window += nums[i] - nums[i - k]   # add entering, drop leaving
        best = max(best, window)
    return best

max_sum_k([2, 1, 5, 1, 3, 2], 3)   # -> 9, from [5, 1, 3]

The variable-size window expands and contracts based on a condition. The right edge always moves forward; the left edge moves forward when the window becomes invalid or when you want to minimize it. This version handles “longest substring without repeating characters” and similar:

python

def longest_unique_substring(s):
    seen = {}          # char -> most recent index
    left = 0
    best = 0
    for right, ch in enumerate(s):
        if ch in seen and seen[ch] >= left:
            left = seen[ch] + 1     # shrink: jump past the repeat
        seen[ch] = right
        best = max(best, right - left + 1)
    return best

longest_unique_substring("abcabcbb")   # -> 3

The critical detail: seen[ch] >= left checks whether the repeat is still inside the current window. Without it, a character that already fell outside the window incorrectly drags the left edge backward, breaking the solution on inputs like “dvdf.”

The tradeoff. O(n) time, O(k) or O(alphabet size) space for whatever you track inside the window. A far better deal than the O(n squared) brute force.

Pattern 2: Two Pointers

Two pointers place one index at each end of a sorted array (or at two positions that move in tandem) and converge toward each other, each step moving the pointer that makes the most progress toward the answer.

The sort order is what makes it work: you can always decide which pointer to move based on whether the current combination is too large or too small.

The recognition signal. A sorted array paired with a pair-finding goal: find two elements that sum to a target, find the closest pair, compare elements from opposite ends. Sorted input is the loudest tell; if the array is not sorted, a hash map is usually the right tool instead.

python

def pair_sum_sorted(a, target):
    left, right = 0, len(a) - 1
    while left < right:
        s = a[left] + a[right]
        if s == target:
            return [left, right]
        elif s < target:
            left += 1       # need bigger, move left up
        else:
            right -= 1      # need smaller, move right down
    return None

pair_sum_sorted([1, 2, 4, 7, 11], 13)   # -> [1, 4], values 2 + 11

A second variant uses both pointers moving in the same direction, with one as a “write position.” This solves in-place problems like removing duplicates from a sorted array in O(1) extra space:

python

def remove_duplicates(nums):
    if not nums:
        return 0
    write = 1
    for read in range(1, len(nums)):
        if nums[read] != nums[write - 1]:
            nums[write] = nums[read]
            write += 1
    return write

The disambiguation. Two pointers require sorted input because the convergence logic relies on knowing which direction to move. On unsorted input, reaching for two pointers is a common mistake. Reach for a hash map instead.

Pattern 3: Fast and Slow Pointers

Two pointers move at different speeds: one moves one step at a time, the other two steps.

In a list with a cycle, the fast pointer will eventually lap the slow one and they will meet inside the cycle.

User's avatar

Continue reading this post for free, courtesy of Rafay Abbasi.

Or purchase a paid subscription.
© 2026 DG Learning · Privacy ∙ Terms ∙ Collection notice
Start your SubstackGet the app
Substack is the home for great culture