>_ devdelight

Free cheat sheet

The TEACH cheat sheet

Every question to ask, 29 patterns, 40 algorithms and the data structures, with code that is compiled and tested in C++ and Python.

New videos, system design breakdowns and the AI news worth your time. The TEACH cheat sheet free when you join. Unsubscribe anytime.

All 14 pages

Printable, and the same sheet as a web page you can come back to. Shown in your theme.

Page 1 of 14 of the TEACH cheat sheet: The TEACH method
1 / 14 The TEACH method
Page 2 of 14 of the TEACH cheat sheet: Patterns, continued
2 / 14 Patterns, continued
Page 3 of 14 of the TEACH cheat sheet: Patterns, the rest
3 / 14 Patterns, the rest
Page 4 of 14 of the TEACH cheat sheet: Dynamic programming is a family
4 / 14 Dynamic programming is a family
Page 5 of 14 of the TEACH cheat sheet: Data structures at a glance
5 / 14 Data structures at a glance
Page 6 of 14 of the TEACH cheat sheet: Big O at a glance
6 / 14 Big O at a glance
Page 7 of 14 of the TEACH cheat sheet: Big O: sorting, graphs and traps
7 / 14 Big O: sorting, graphs and traps
Page 8 of 14 of the TEACH cheat sheet: Language quick reference
8 / 14 Language quick reference
Page 9 of 14 of the TEACH cheat sheet: Test cases
9 / 14 Test cases
Page 10 of 14 of the TEACH cheat sheet: TEACH, step by step
10 / 14 TEACH, step by step
Page 11 of 14 of the TEACH cheat sheet: Algorithms at a glance
11 / 14 Algorithms at a glance
Page 12 of 14 of the TEACH cheat sheet: Algorithms, continued
12 / 14 Algorithms, continued
Page 13 of 14 of the TEACH cheat sheet: Algorithms, continued
13 / 14 Algorithms, continued
Page 14 of 14 of the TEACH cheat sheet: Algorithms, continued
14 / 14 Algorithms, continued

Free code, tested

Three full snippets so you can judge the quality before you sign up. Each one is compiled and run against its tests, in both languages.

BFS

O(V + E) · O(V)

Fewest steps when every step costs the same.

Show codeC++ and Python
// LC 994 · BFS, multi-source shortest steps on a grid
// O(V + E) time, O(V) space (here V = m * n)
#include <queue>
#include <utility>
#include <vector>
using namespace std;

int orangesRotting(vector<vector<int>> g) {            // by value: we mark cells in place
    int m = g.size(), n = g[0].size(), fresh = 0, t = 0;
    queue<pair<int, int>> q;
    for (int i = 0; i < m; i++)
        for (int j = 0; j < n; j++) {
            if (g[i][j] == 2) q.push({i, j});
            else if (g[i][j] == 1) fresh++;
        }
    int d[] = {0, 1, 0, -1, 0};
    for (; !q.empty() && fresh; t++)                    // one level per minute
        for (int s = q.size(); s--; ) {
            auto [x, y] = q.front(); q.pop();
            for (int k = 0; k < 4; k++) {
                int a = x + d[k], b = y + d[k + 1];
                if (a < 0 || b < 0 || a >= m || b >= n || g[a][b] != 1) continue;
                g[a][b] = 2; fresh--;                   // mark seen when pushing
                q.push({a, b});
            }
        }
    return fresh ? -1 : t;
}
# LC 994 · BFS, multi-source shortest steps on a grid
# O(V + E) time, O(V) space (here V = m * n)
from collections import deque

def oranges_rotting(grid):
    g = [row[:] for row in grid]                        # copy: we mark cells in place
    m, n = len(g), len(g[0])
    q = deque((i, j) for i in range(m) for j in range(n) if g[i][j] == 2)
    fresh = sum(row.count(1) for row in g)
    t = 0
    while q and fresh:
        for _ in range(len(q)):                         # one level per minute
            x, y = q.popleft()
            for a, b in ((x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)):
                if 0 <= a < m and 0 <= b < n and g[a][b] == 1:
                    g[a][b] = 2                         # mark seen when pushing
                    fresh -= 1
                    q.append((a, b))
        t += 1
    return -1 if fresh else t

C++ compiled with clang (C++17) and run against 305 tests. Python 3.14 run against 305.

Binary search

O(log n) · O(1), times the cost of ok()

Sorted input, or a yes or no check that flips once.

Show codeC++ and Python
// LC 704 · 34 · 1011 · Binary search, half-open [lo, hi)
// O(log n) time, O(1) space, times the cost of ok()
#include <algorithm>
#include <numeric>
#include <vector>
using namespace std;

int lowerBound(const vector<int>& a, int t) {      // first i with a[i] >= t  (LC 704: then check i < n && a[i] == t)
    int lo = 0, hi = a.size();
    while (lo < hi) {
        int mid = lo + (hi - lo) / 2;
        if (a[mid] >= t) hi = mid; else lo = mid + 1;
    }
    return lo;
}

int upperBound(const vector<int>& a, int t) {      // first i with a[i] > t  (LC 34: [lower, upper - 1] if lower < upper)
    int lo = 0, hi = a.size();
    while (lo < hi) {
        int mid = lo + (hi - lo) / 2;
        if (a[mid] > t) hi = mid; else lo = mid + 1;
    }
    return lo;
}

int shipWithinDays(const vector<int>& w, int days) {   // LC 1011: smallest feasible capacity
    int lo = *max_element(w.begin(), w.end());
    int hi = accumulate(w.begin(), w.end(), 0) + 1;
    while (lo < hi) {
        int mid = lo + (hi - lo) / 2, need = 1, load = 0;
        for (int x : w) {
            if (load + x > mid) need++, load = 0;
            load += x;
        }
        if (need <= days) hi = mid; else lo = mid + 1;   // ok(mid)
    }
    return lo;
}
# LC 704 · 34 · 1011 · Binary search, half-open [lo, hi)
# O(log n) time, O(1) space, times the cost of ok()

def lower_bound(a, t):          # first i with a[i] >= t  (LC 704: then check i < n and a[i] == t)
    lo, hi = 0, len(a)
    while lo < hi:
        mid = lo + (hi - lo) // 2
        if a[mid] >= t:
            hi = mid
        else:
            lo = mid + 1
    return lo

def upper_bound(a, t):          # first i with a[i] > t  (LC 34: [lower, upper - 1] if lower < upper)
    lo, hi = 0, len(a)
    while lo < hi:
        mid = lo + (hi - lo) // 2
        if a[mid] > t:
            hi = mid
        else:
            lo = mid + 1
    return lo

def ship_within_days(w, days):  # LC 1011: smallest feasible capacity
    lo, hi = max(w), sum(w) + 1
    while lo < hi:
        mid = lo + (hi - lo) // 2
        need, load = 1, 0
        for x in w:
            if load + x > mid:
                need, load = need + 1, 0
            load += x
        if need <= days:        # ok(mid)
            hi = mid
        else:
            lo = mid + 1
    return lo

C++ compiled with clang (C++17) and run against 514 tests. Python 3.14 run against 513.

Hash map and set

You keep asking “have I seen this?” or need counts.

Show codeC++ and Python
// Hash map and set: unordered_map, unordered_set
#include <optional>
#include <unordered_map>
#include <unordered_set>
#include <vector>
using namespace std;

unordered_map<int, int> countFreq(const vector<int>& a) {
    unordered_map<int, int> cnt;
    for (int x : a) cnt[x]++;                       // get + put: O(1) avg per key
    return cnt;                                     // worst case, all keys collide: O(n) per op
}
bool hasKey(const unordered_map<int, int>& m, int k) { return m.count(k) > 0; }   // contains: O(1) avg
void removeKey(unordered_map<int, int>& m, int k) { m.erase(k); }                 // delete: O(1) avg
int sumValues(const unordered_map<int, int>& m) {   // iterate: O(n)
    int s = 0;
    for (auto& [k, v] : m) s += v;
    return s;
}
optional<int> firstRepeat(const vector<int>& a) {   // "have I seen this?", nullopt if none
    unordered_set<int> seen;
    for (int x : a)
        if (!seen.insert(x).second) return x;       // insert fails if present: O(1) avg
    return nullopt;
}
# Hash map and set: dict, Counter, set
from collections import Counter, defaultdict

def count_freq(a):
    return Counter(a)                       # counts in one pass: O(n), each put O(1) avg

def group_by_parity(a):
    groups = defaultdict(list)              # missing key starts as []
    for x in a:
        groups[x % 2].append(x)             # get + put: O(1) avg
    return groups

def has_key(m, k): return k in m            # contains: O(1) avg
def remove_key(m, k): m.pop(k, None)        # delete: O(1) avg
def sum_values(m): return sum(m.values())   # iterate: O(n)
# worst case, all keys collide: O(n) per operation

def first_repeat(a):                        # "have I seen this?", None if none
    seen = set()
    for x in a:
        if x in seen: return x              # contains: O(1) avg
        seen.add(x)                         # put: O(1) avg
    return None

C++ compiled with clang (C++17) and run against 13 tests. Python 3.14 run against 13.

Patterns that move

Eight of the 29 patterns, each with a short loop. The other 21 and all the code are in the sheet.

Two pointers: a short looping diagram of the idea

Two pointers

Sorted input, a pair, or matching ends.

Fast and slow pointers: a short looping diagram of the idea

Fast and slow pointers

A cycle in a linked list, or its middle.

Sliding window: a short looping diagram of the idea

Sliding window

The longest or shortest run under a rule.

Binary search on a boundary: a short looping diagram of the idea

Binary search on a boundary

Sorted, or where a yes or no check flips.

Cyclic sort: a short looping diagram of the idea

Cyclic sort

Values 1 to n. Find missing or doubled.

In-place list reversal: a short looping diagram of the idea

In-place list reversal

Reverse a linked list, or a stretch of it.

Stack and monotonic stack: a short looping diagram of the idea

Stack and monotonic stack

Brackets, or the next greater element.

Monotonic deque: a short looping diagram of the idea

Monotonic deque

The max or min of every sliding window.

Big-O at a glance

Drag the input size to see which costs survive. The data structure, sorting, graph and cost-trap tables are in the full sheet.

n = 100,000

Drag n from 1 to a billion. The bars show how many operations each cost class needs. The verdict assumes about 100,000,000 simple operations per second in C++, 10,000,000 in Python, and a limit of about a second.

  1. O(1)1instant
  2. O(log n)17instant
  3. O(n)100,000instant
  4. O(n log n)1.7 × 10⁶fine
  5. O(n²)1.0 × 10¹⁰too slow
  6. O(2ⁿ)more than 10¹⁰⁰too slow
  7. O(n!)more than 10¹⁰⁰too slow

At n = 100,000 in C++, aim for O(n log n) or better.

Data structures

Average case unless a column says worst. Space is O(n) in the number of stored items; a trie is O(total characters).

StructureAccessSearchInsertDeleteWorst case
ArrayO(1)excellentO(n)goodO(n)goodO(n)goodsame
Dynamic array (append)O(1)excellentO(n)goodO(1) amortizedexcellentO(n) middle, O(1) at the endgoodappend O(n) when it grows
Linked listO(n)goodO(n)goodO(1) at a known nodeexcellentO(1) at a known node, doubly linked listexcellentsame
Stack, queue, dequeO(n) linked, O(1) array-backedgoodO(n)goodO(1)excellentO(1)excellentsame
Hash map, hash setn/aO(1)excellentO(1)excellentO(1)excellentO(n) when every key collides, or on a rehashbad
Binary search treeO(log n)excellentO(log n)excellentO(log n)excellentO(log n)excellentO(n) when skewedbad
Balanced tree (AVL, red-black)O(log n)excellentO(log n)excellentO(log n)excellentO(log n)excellentO(log n)excellent
Binary heappeek O(1)excellentO(n)goodO(log n)excellentpop min O(log n)excellentpush and pop O(log n); build from n items O(n)good
Trie (key length L)n/aO(L)excellentO(L)excellentO(L)excellentspace O(total characters)
Union-findn/afind O(α(n)) amortizedexcellentunion O(α(n)) amortizedexcellentn/aα(n) is below 5 for any real n

Data structures at a glance

What each one is for. The costs of every move are in the sheet.

Array: a short looping diagram of the idea

Array

You need items by position, or one pass in order.

String: a short looping diagram of the idea

String

Text. Count letters with a 26-slot array.

Hash map and set: a short looping diagram of the idea

Hash map and set

You keep asking “have I seen this?” or need counts.

Stack: a short looping diagram of the idea

Stack

The newest item matters first. Brackets, undo, next greater.

Queue and deque: a short looping diagram of the idea

Queue and deque

First in, first out. BFS, or a window you slide.

Linked list: a short looping diagram of the idea

Linked list

You splice nodes in and out. LRU cache: a hash map plus a doubly linked list.

Heap: a short looping diagram of the idea

Heap

You keep needing the smallest or the largest.

Binary tree and BST: a short looping diagram of the idea

Binary tree and BST

Hierarchy, or sorted order that changes as you go.

Trie: a short looping diagram of the idea

Trie

Prefix search and autocomplete over many words.

Graph, adjacency list: a short looping diagram of the idea

Graph, adjacency list

Things connect to things. Keep each node’s neighbors.

Union-find: a short looping diagram of the idea

Union-find

Groups merge as edges arrive, and you ask “same group?”

Ordered map and set: a short looping diagram of the idea

Ordered map and set

Keys in sorted order, or the nearest key above or below.

40 algorithms

Time and space, and the trigger that tells you to reach for each one. Templates and tested code are in the sheet.

Sorting and selection

Merge sort

O(n log n) · O(n) extra on arrays, O(1) on a linked list with bottom-up merging · stable

Stable sort, or sorting a linked list.

Quicksort

O(n log n) avg, O(n²) worst · O(log n) stack, not stable

Fast in place on arrays.

Quickselect

O(n) avg, O(n²) worst · O(1) iterative

The k-th smallest or largest, no full sort.

Heap sort

O(n log n) · O(1), not stable

In place with a guaranteed n log n.

Counting and bucket sort

O(n + k) time and space, k = value range · LC 347 bucketed by count is O(n) · bucket sort: average O(n) if uniform, worst O(n²)

A small value range, or items bucketed by count.

Search

Binary search

O(log n) · O(1), times the cost of ok()

Sorted input, or a yes or no check that flips once.

Graph traversal

BFS

O(V + E) · O(V)

Fewest steps when every step costs the same.

DFS

O(V + E) · O(V) stack

Visit everything, components, cycles, paths.

Topological sort

O(V + E) · O(V)

An order that respects dependencies.

Shortest paths, MST, components

Dijkstra

O((V + E) log V) · O(V + E) with a lazy heap

Shortest path, no negative weights.

Bellman-Ford

O(V · E) · O(V)

Negative edges, or at most k edges.

0-1 BFS

O(V + E) · O(V)

Every edge costs 0 or 1.

Floyd-Warshall

O(V³) · O(V²)

All pairs, small V.

Kruskal and Prim (MST)

Kruskal O(E log E) · Prim O(V²) or O((V + E) log V) · O(V + E)

The cheapest way to connect everything.

SCC · Kosaraju, Tarjan

O(V + E) · O(V)

Groups that all reach each other, in a directed graph.

Union-find

O(α(n)) per op, amortized · O(n)

Groups merge as edges arrive. Same group?

Ranges and windows

Two pointers, sliding window

O(n) · O(1), or O(k) with a counts map

A contiguous range under a rule. A sum target needs positives.

Prefix sums, diff array

O(n) build · O(1) range sum, or O(1) range adds then one pass

Many range sums, or many range adds.

Recursion and DP

Backtracking

O(n · n!) permutations, O(n · 2^n) subsets · O(n) depth

Every subset, permutation or placement.

DP template

O(states × transitions) · O(states)

Subproblems repeat.

Bits, strings, sampling

Bit tricks

O(1) per bit operation (fixed-width ints) · one lone number is one O(n) pass

Parity, sets as masks, one lone number.

KMP, rolling hash (advanced)

KMP O(n + m) · O(m) · hash O(n + m) avg, O(n · m) worst

Find a pattern in a text.

Reservoir sampling

O(n) · O(1)

A fair pick from a stream of unknown length.

More on graphs and trees

Bipartite check

O(V + E) · O(V)

Split nodes into two sides, or find an odd cycle.

Lowest common ancestor

O(n) one pass · O(n log n) build, O(log n) a query with binary lifting

The first node above two given nodes.

Math and randomness

GCD, sieve, fast power

gcd O(log n) · sieve O(n log log n) · power O(log n)

Divisibility, primes up to n, or x to a huge power.

Fisher-Yates shuffle

O(n) · O(1) extra

A uniform random order, one swap per position.

More interview staples

Fenwick tree (BIT)

update and prefix query O(log n) · O(n)

Prefix sums that change.

Segment tree

update and range query O(log n) · O(n)

Range min, max or sum with updates.

Iterative tree traversal

O(n) · O(h)

Deep trees, or in-order with an explicit stack.

Top-down memoization

states × work per state · O(states)

A recursion whose subproblems repeat.

BFS on an implicit graph

O(states × moves) · O(states)

Fewest steps where the nodes are built, not given.

Backtracking with duplicates

O(n · 2^n) subsets · O(n) depth

Subsets or permutations of repeated values.

Serialize a tree

O(n) · O(n)

Send a tree as text and rebuild it.

LRU cache design

get and put O(1) · O(capacity)

Evict the least recently used item.

BST properties

O(n) · O(h)

Is it a BST, or the kth smallest.

Divide and conquer, build a tree

O(n) with an index map · O(n)

Split in two, solve each half, combine.

Eulerian path, Hierholzer

O(E log E) with sorted neighbours · O(E)

Use every edge exactly once.

Digit arithmetic with carry

O(n) · O(n)

Add, multiply or reverse numbers too big for an int.

Geometry basics

O(1) per test · slope counting O(n²) with a hash map, O(n² log n) with std::map

Points, lines and rectangles on a plane.

Get the sheet, then the next video

New videos, system design breakdowns and the AI news worth your time. The TEACH cheat sheet free when you join. Unsubscribe anytime.