Skip to main content

LeetCode Patterns Cheat Sheet 2026

All 21 algorithmic patterns — when-to-use signals, time & space complexity, and code templates in Python, Java & C++. One page. Free forever.

By Syed Peera Saheb · · Full pattern guide →
Pattern guide with templates

Pattern Recognition Quick Reference

When you see these signals in a problem statement, reach for the corresponding pattern immediately. Recognizing the pattern is half the work — the template handles the rest.

Problem signal Pattern to use Complexity
Finding max/min subarray of size k Sliding Window O(n)
Pair sum in sorted array Two Pointers O(n)
Searching in sorted array Binary Search O(log n)
Two sum (find complement) Hash Map / Set O(1) average for lookup/insert, O(n) space
Tree height/depth Trees / DFS O(n)
Shortest path in unweighted graph Queue / BFS O(V + E) for graphs, O(n) for trees
Fibonacci and climbing stairs Dynamic Programming Depends on state space
Valid parentheses / bracket matching Stack O(n)
Kth largest/smallest element Heap / Priority Queue O(log n) insert/delete, O(1) peek
Generate all permutations/combinations/subsets Backtracking Exponential
Merge intervals Intervals O(n log n)
Range sum queries Prefix Sum O(n) build, O(1) per query
Number of islands Graphs O(V + E)
Implement Trie (insert/search/startsWith) Trie O(m) per operation where m is word length
Number of connected components Union Find O(α(n)) per operation
Largest rectangle in histogram Monotonic Stack O(n)
Course Schedule (detect cycle) Topological Sort O(V + E)
Detecting cycles (Floyd's algorithm) Linked List O(n)
Jump game Greedy O(n log n)
Single number (XOR trick) Bit Manipulation O(1) or O(log n) for most operations
Rotate image 90° Matrix O(m × n)

All 21 Patterns — Complete Reference

01

Sliding Window

Efficiently process subarrays or substrings of a fixed or variable size.

Time: O(n) Space: O(k) where k is the window size or alphabet size
  • Finding max/min subarray of size k
  • Longest substring without repeating characters
  • Minimum window containing all characters
def sliding_window(arr, k):
    left = 0
    result = 0
    window_state = {}  # track window contents

    for right in range(len(arr)):
        # Expand window: add arr[right]

        # Shrink window when constraint violated
        while False:  # replace with invalid condition
            # Remove arr[left] from state
            left += 1

        # Update result
        result = max(result, right - left + 1)
    return result
Full guide + practice problems →
02

Two Pointers

Use two indices moving toward each other or in the same direction to solve linear problems.

Time: O(n) Space: O(1)
  • Pair sum in sorted array
  • Removing duplicates in-place
  • Container with most water
def two_pointers(arr, target):
    left, right = 0, len(arr) - 1
    while left < right:
        s = arr[left] + arr[right]
        if s == target:
            return [left, right]
        elif s < target:
            left += 1
        else:
            right -= 1
    return []
Full guide + practice problems →
04

Hash Map / Set

Trade space for time using O(1) lookup to find pairs, duplicates, and frequencies.

Time: O(1) average for lookup/insert, O(n) space Space: O(n)
  • Two sum (find complement)
  • Anagram grouping
  • Longest consecutive sequence
from collections import Counter

# Frequency count
freq = Counter(arr)

# Two sum
def two_sum(nums, target):
    seen = {}  # value -> index
    for i, num in enumerate(nums):
        complement = target - num
        if complement in seen:
            return [seen[complement], i]
        seen[num] = i
    return []
Full guide + practice problems →
05

Trees / DFS

Recursive and iterative depth-first traversal for tree structure problems.

Time: O(n) Space: O(h) where h is height; O(n) worst case (skewed)
  • Tree height/depth
  • Path sum problems
  • Lowest common ancestor
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

# Generic DFS template
def dfs(node):
    if not node:
        return  # base case
    # Pre-order: process node here
    dfs(node.left)
    # In-order: process node here
    dfs(node.right)
    # Post-order: process node here

# Path sum
def has_path_sum(root, target):
    if not root:
        return False
    if not root.left and not root.right:
        return root.val == target
    return (has_path_sum(root.left, target - root.val) or
            has_path_sum(root.right, target - root.val))
Full guide + practice problems →
06

Queue / BFS

Level-by-level traversal for shortest paths and layer-based problems.

Time: O(V + E) for graphs, O(n) for trees Space: O(V) for the queue
  • Shortest path in unweighted graph
  • Level-order tree traversal
  • Rotting oranges / island flooding
from collections import deque

def bfs(graph, start):
    visited = {start}
    queue = deque([start])

    while queue:
        node = queue.popleft()
        # process node

        for neighbor in graph[node]:
            if neighbor not in visited:
                visited.add(neighbor)
                queue.append(neighbor)
Full guide + practice problems →
07

Dynamic Programming

Break problems into overlapping subproblems and build up solutions bottom-up.

Time: Depends on state space Space: O(n) with space optimization
  • Fibonacci and climbing stairs
  • Knapsack variants
  • Longest common subsequence
# 1D DP (Climbing Stairs)
def climb_stairs(n):
    dp = [0] * (n + 1)
    dp[0] = dp[1] = 1
    for i in range(2, n + 1):
        dp[i] = dp[i-1] + dp[i-2]
    return dp[n]

# 2D DP (Unique Paths)
def unique_paths(m, n):
    dp = [[1] * n for _ in range(m)]
    for i in range(1, m):
        for j in range(1, n):
            dp[i][j] = dp[i-1][j] + dp[i][j-1]
    return dp[m-1][n-1]
Full guide + practice problems →
08

Stack

LIFO structure for matching brackets, evaluating expressions, and monotonic problems.

Time: O(n) Space: O(n)
  • Valid parentheses / bracket matching
  • Next greater element
  • Daily temperatures
# Monotonic decreasing stack (next greater element)
def next_greater(arr):
    result = [-1] * len(arr)
    stack = []  # stores indices

    for i in range(len(arr)):
        while stack and arr[stack[-1]] < arr[i]:
            result[stack.pop()] = arr[i]
        stack.append(i)
    return result
Full guide + practice problems →
09

Heap / Priority Queue

Efficiently track the k-th largest/smallest element or merge sorted sequences.

Time: O(log n) insert/delete, O(1) peek Space: O(n)
  • Kth largest/smallest element
  • Merge k sorted lists
  • Task scheduler
import heapq

# Min-heap
min_heap = []
heapq.heappush(min_heap, val)
top = heapq.heappop(min_heap)   # smallest
peek = min_heap[0]

# Max-heap (negate values)
max_heap = []
heapq.heappush(max_heap, -val)
top = -heapq.heappop(max_heap)  # largest

# Kth largest element
def kth_largest(nums, k):
    return heapq.nlargest(k, nums)[-1]
Full guide + practice problems →
10

Backtracking

Explore all possibilities recursively, pruning invalid branches early.

Time: Exponential Space: O(n) call stack depth
  • Generate all permutations/combinations/subsets
  • N-Queens
  • Sudoku solver
def backtrack(result, current, start, nums):
    result.append(current[:])  # record current state

    for i in range(start, len(nums)):
        # Prune: skip duplicates
        if i > start and nums[i] == nums[i-1]:
            continue
        current.append(nums[i])              # choose
        backtrack(result, current, i + 1, nums)  # explore
        current.pop()                        # un-choose
Full guide + practice problems →
11

Intervals

Merge, insert, and count overlapping intervals after sorting by start time.

Time: O(n log n) Space: O(n)
  • Merge intervals
  • Insert interval
  • Meeting rooms (can attend all?)
def merge_intervals(intervals):
    intervals.sort(key=lambda x: x[0])
    merged = [intervals[0]]

    for start, end in intervals[1:]:
        last = merged[-1]
        if start <= last[1]:
            last[1] = max(last[1], end)  # overlap: extend
        else:
            merged.append([start, end])  # no overlap: new interval
    return merged
Full guide + practice problems →
12

Prefix Sum

Precompute cumulative sums to answer range queries in O(1).

Time: O(n) build, O(1) per query Space: O(n)
  • Range sum queries
  • Subarray sum equals k
  • Number of subarrays with given sum
def build_prefix(arr):
    prefix = [0] * (len(arr) + 1)
    for i in range(len(arr)):
        prefix[i + 1] = prefix[i] + arr[i]
    return prefix

def range_sum(prefix, l, r):
    return prefix[r + 1] - prefix[l]  # inclusive [l, r]
Full guide + practice problems →
13

Graphs

DFS and BFS on adjacency lists for connectivity, cycles, and path problems.

Time: O(V + E) Space: O(V) for visited set
  • Number of islands
  • Clone graph
  • Course schedule (cycle detection)
def num_islands(grid):
    count = 0
    for r in range(len(grid)):
        for c in range(len(grid[0])):
            if grid[r][c] == '1':
                dfs(grid, r, c)
                count += 1
    return count

def dfs(grid, r, c):
    if r < 0 or r >= len(grid) or c < 0 or c >= len(grid[0]) or grid[r][c] != '1':
        return
    grid[r][c] = '0'  # mark visited
    dfs(grid, r + 1, c)
    dfs(grid, r - 1, c)
    dfs(grid, r, c + 1)
    dfs(grid, r, c - 1)
Full guide + practice problems →
14

Trie

Prefix tree for efficient string search, autocomplete, and word matching.

Time: O(m) per operation where m is word length Space: O(ALPHABET_SIZE × m × n)
  • Implement Trie (insert/search/startsWith)
  • Word search II
  • Design add/search words
class TrieNode:
    def __init__(self):
        self.children = {}
        self.is_end = False

class Trie:
    def __init__(self):
        self.root = TrieNode()

    def insert(self, word):
        node = self.root
        for ch in word:
            if ch not in node.children:
                node.children[ch] = TrieNode()
            node = node.children[ch]
        node.is_end = True

    def search(self, word):
        node = self.root
        for ch in word:
            if ch not in node.children:
                return False
            node = node.children[ch]
        return node.is_end
Full guide + practice problems →
15

Union Find

Disjoint set union for grouping, connectivity, and cycle detection.

Time: O(α(n)) per operation Space: O(n)
  • Number of connected components
  • Redundant connection (cycle detection)
  • Accounts merge
class UnionFind:
    def __init__(self, n):
        self.parent = list(range(n))
        self.rank = [0] * n

    def find(self, x):
        if self.parent[x] != x:
            self.parent[x] = self.find(self.parent[x])  # path compression
        return self.parent[x]

    def union(self, x, y):
        px, py = self.find(x), self.find(y)
        if px == py:
            return False
        if self.rank[px] < self.rank[py]:
            self.parent[px] = py
        elif self.rank[px] > self.rank[py]:
            self.parent[py] = px
        else:
            self.parent[py] = px
            self.rank[px] += 1
        return True
Full guide + practice problems →
16

Monotonic Stack

Maintain a sorted stack to find next/previous greater or smaller elements in O(n).

Time: O(n) Space: O(n)
  • Largest rectangle in histogram
  • Trapping rain water
  • Daily temperatures
# Largest Rectangle in Histogram
def largest_rectangle(heights):
    stack = [-1]
    max_area = 0

    for i in range(len(heights) + 1):
        h = 0 if i == len(heights) else heights[i]
        while stack[-1] != -1 and heights[stack[-1]] >= h:
            height = heights[stack.pop()]
            width = i - stack[-1] - 1
            max_area = max(max_area, height * width)
        stack.append(i)
    return max_area
Full guide + practice problems →
17

Topological Sort

Linear ordering of vertices in a DAG — essential for dependency problems.

Time: O(V + E) Space: O(V)
  • Course Schedule (detect cycle)
  • Course Schedule II (ordering)
  • Alien dictionary
from collections import deque

# Kahn's Algorithm (BFS-based)
def topo_sort(n, prerequisites):
    in_degree = [0] * n
    adj = [[] for _ in range(n)]

    for a, b in prerequisites:
        adj[b].append(a)
        in_degree[a] += 1

    queue = deque(i for i in range(n) if in_degree[i] == 0)
    order = []

    while queue:
        node = queue.popleft()
        order.append(node)
        for nei in adj[node]:
            in_degree[nei] -= 1
            if in_degree[nei] == 0:
                queue.append(nei)

    return order if len(order) == n else []  # empty = cycle exists
Full guide + practice problems →
18

Linked List

Pointer manipulation for in-place list operations without extra memory.

Time: O(n) Space: O(1) for in-place operations
  • Detecting cycles (Floyd's algorithm)
  • Reversing a linked list
  • Finding middle of list
class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

# Reverse linked list in-place
def reverse(head):
    prev, curr = None, head
    while curr:
        nxt = curr.next
        curr.next = prev
        prev = curr
        curr = nxt
    return prev

# Fast / slow pointer
def has_cycle(head):
    slow = fast = head
    while fast and fast.next:
        slow = slow.next
        fast = fast.next.next
        if slow is fast:
            return True
    return False
Full guide + practice problems →
19

Greedy

Make the locally optimal choice at each step to achieve a globally optimal solution.

Time: O(n log n) Space: O(1)
  • Jump game
  • Gas station
  • Meeting rooms
# Jump Game II — greedy
def jump(nums):
    jumps = current_end = farthest = 0
    for i in range(len(nums) - 1):
        farthest = max(farthest, i + nums[i])
        if i == current_end:
            jumps += 1
            current_end = farthest
    return jumps
Full guide + practice problems →
20

Bit Manipulation

Use bitwise operations to solve XOR, subset, and number theory problems.

Time: O(1) or O(log n) for most operations Space: O(1)
  • Single number (XOR trick)
  • Number of 1 bits (Hamming weight)
  • Counting bits
# Common bit tricks
get_bit = lambda n, i: (n >> i) & 1
set_bit = lambda n, i: n | (1 << i)
clear_bit = lambda n, i: n & ~(1 << i)
is_power_of_2 = lambda n: n > 0 and (n & (n - 1)) == 0
lowest_set_bit = lambda n: n & (-n)
clear_lowest_bit = lambda n: n & (n - 1)

# XOR: find single number where all others appear twice
from functools import reduce
single_number = lambda nums: reduce(lambda a, b: a ^ b, nums)
Full guide + practice problems →
21

Matrix

Navigate 2D grids with DFS/BFS, rotation, spiral traversal, and flood fill.

Time: O(m × n) Space: O(m × n) for BFS/DFS, O(1) for in-place tricks
  • Rotate image 90°
  • Spiral matrix traversal
  • Set matrix zeros
from collections import deque

DIRS = [(1, 0), (-1, 0), (0, 1), (0, -1)]

def bfs_grid(grid, start_r, start_c):
    rows, cols = len(grid), len(grid[0])
    queue = deque([(start_r, start_c)])
    visited = {(start_r, start_c)}

    while queue:
        r, c = queue.popleft()
        for dr, dc in DIRS:
            nr, nc = r + dr, c + dc
            if 0 <= nr < rows and 0 <= nc < cols and (nr, nc) not in visited:
                visited.add((nr, nc))
                queue.append((nr, nc))
Full guide + practice problems →

Ready to practice?

Use the full Coding Interview Patterns guide to study each pattern in depth, then solve curated problems from our problem set. Filter by company to target the exact patterns asked at Google, Meta, Amazon, and Microsoft.

Buy me a coffee