Cheat sheet · DSA for Interviews, From Zero
DSA cheat sheet
Complexity tables, the patterns with the signal that tells you when to use each, short JavaScript templates and the traps. Read the signal in the problem, name the pattern, then write the template.
blogs · jp-blogs.vercel.app/cheatsheets/series/dsa
Big-O and size limitsLesson 12 →
| Big-O | Typical |
|---|---|
| O(1) | arr[i], Map get |
| O(log n) | Halve each step |
| O(n) | One loop |
| O(n log n) | Good sorting |
| O(n²) | Loop in a loop |
| O(2ⁿ) | Every subset |
- includes, indexOf, find
- O(n) hidden loop
- shift, unshift, splice
- O(n): items move
- slice, spread, concat
- O(n): copies
- n ≤ 20
- 2ⁿ is fine (n ≤ 10: n!)
- n ≤ 5,000
- n² is fine (n ≤ 500: n³)
- n ≤ 10⁶
- n log n or n
- n ≥ 10⁹
- log n or O(1)
Tip: About 10⁸ simple steps per second. Sequential loops add, nested loops multiply. Quote the worst case.
Maths and recursionLesson 13 →
- Digit loop (
n % 10,Math.floor(n / 10)) is O(log n). Divisors come in pairs, so loop whilei * i <= n: O(√n). 0 and 1 are not prime. - Sieve: all primes up to n in O(n log log n). Euclid gcd and fast power: O(log n).
- Recursion needs a base case, a smaller call and progress. Space is O(depth).
Watch out: Plain fib(30) makes about 2.7 million calls. A memo makes 59.
SortingLesson 17 →
| Sort | Best / worst | Space | Stable |
|---|---|---|---|
| Selection | n² / n² | O(1) | No |
| Bubble (early exit) | n / n² | O(1) | Yes |
| Insertion | n / n² | O(1) | Yes |
| Merge | n log n / n log n | O(n) | Yes |
| Quick (random pivot) | n log n / n² rare | O(log n) | No |
- Merge:
a[i] <= b[j]keeps it stable. Merging two sorted arrays is O(n + m). - Quickselect finds the k-th item in O(n) average.
Watch out: sort() with no comparator sorts as text ("100" before "9"). Use (a, b) => a - b, never a boolean.
Prefix sums, Kadane, in placeLesson 20 →
- Range sum l..r
pre[r + 1] - pre[l],prestarts with 0- Subarray sums to k
- Count earlier prefix sums equal
sum - k - Kadane
cur = max(x, cur + x); answer is the bestcur- In place (dedupe, zeros)
- Read and write pointers, O(1) space
- Rotate right by k
- Reverse all, then each part;
k % n
const seen = new Map([[0, 1]]);
let sum = 0, count = 0;
for (const x of nums) {
sum += x;
count += seen.get(sum - k) ?? 0;
seen.set(sum, (seen.get(sum) ?? 0) + 1);
}Works with negatives.
Watch out: Start Kadane at nums[0], not 0, or all-negative input returns 0.
Two pointersLesson 21 →
| Form | Use for |
|---|---|
| Opposite ends (sorted) | Pair sum, 3Sum, container, palindrome |
| Same direction | Remove duplicates, subsequence check |
let l = 0, r = nums.length - 1;
while (l < r) {
const s = nums[l] + nums[r];
if (s === target) return [l, r];
if (s < target) l++; else r--;
}- 3Sum: sort, fix one value, two pointers on the rest. O(n²).
- Container: move the shorter line inwards.
Sliding window and stringsLesson 23 →
let l = 0;
for (let r = 0; r < n; r++) {
add(nums[r]);
while (invalid())
remove(nums[l++]);
best = Math.max(best, r - l + 1);
}O(n): l and r never move back, at most 2n steps.
| Window | Longest | Shortest |
|---|---|---|
| Shrink while | invalid | valid |
| Record | after loop | inside loop |
| best starts at | 0 | Infinity |
- Fixed size k: drop
nums[i - k]wheni >= k, use the window wheni >= k - 1. - Exactly k = atMost(k) − atMost(k − 1). Count windows by adding
r - l + 1. - Strings are immutable:
joinonce. Longest palindrome: expand around 2n − 1 centres, O(n²).
Watch out: Windows need non-negative values. With negatives use prefix sums and a Map.
Hashing patternsLesson 26 →
const seen = new Map();
for (let i = 0; i < nums.length; i++) {
const j = seen.get(target - nums[i]);
if (j !== undefined) return [j, i];
seen.set(nums[i], i); // then store
}Pairs O(n²), sort + pointers O(n log n), Map O(n) time and space.
- Count:
freq.set(x, (freq.get(x) ?? 0) + 1). Fixed range: counting array. - Anagram key: sorted letters or
counts.join(","), neverjoin(""). A Map compares arrays by identity. - Top k frequent: count, then buckets by count. Majority: Boyer–Moore vote.
Binary searchLesson 28 →
let lo = 0, hi = nums.length; // [lo, hi)
while (lo < hi) {
const mid = (lo + hi) >> 1;
if (nums[mid] < target) lo = mid + 1;
else hi = mid;
}
return lo; // first nums[i] >= target- Pick one style. Closed
[lo, hi]:lo <= hi,mid ± 1. Half-open:lo < hi,hi = mid. - First / last of x:
lowerBound(x),upperBound(x) - 1. - Rotated array: one half is sorted. Compare
nums[lo]withnums[mid].
- On the answer: set the range
lo..hiof answers. - Write
works(x), one O(n) pass (Koko: sum ofMath.ceil(pile / k)≤ h). - Check false…false, true…true. Find the first true: O(n log range).
Recursion and backtrackingLesson 33 →
// n = nums.length
function walk(start, path) {
out.push([...path]); // copy
for (let i = start; i < n; i++) {
path.push(nums[i]); // choose
walk(i + 1, path); // explore
path.pop(); // un-choose
}
}- Duplicates
- Sort, skip
i > start && nums[i] === nums[i-1] - Permutations
- Loop from 0 with a
usedarray - Combination sum
- Recurse with
ito reuse; prune
Watch out: Pushing path without copying fills out with empty arrays. Forgetting to undo is the most common bug.
Linked listsLesson 36 →
let prev = null, cur = head;
while (cur) {
const next = cur.next; // save first
cur.next = prev;
prev = cur;
cur = next;
}
return prev;O(n) time, O(1) space.
- Insert at head or after a held node is O(1); access index i is O(i). A dummy head removes the delete-head special case.
- Slow 1 step, fast 2: middle and cycle (Floyd). Cycle start: reset one pointer to head, step both by 1.
- n-th from end: send
fastn ahead, then move both.
Stacks and queuesLesson 40 →
const ans = Array(n).fill(-1);
const st = [];
for (let i = 0; i < n; i++) {
while (st.length &&
nums[st.at(-1)] < nums[i])
ans[st.pop()] = nums[i];
st.push(i);
}Next greater element. Each index is pushed and popped once: O(n).
- Stack = array with
pushandpop. Brackets: closer must match the top; fail on mismatch, empty, leftovers. - Queue: use a head index, not
shift()(O(n)), or BFS turns O(n²). - Min stack: store the minimum beside each item.
- Circular array: loop
2nwithi % n.
Trees and BSTsLesson 43 →
function height(node) {
if (node === null) return 0; // base case
return 1 + Math.max(
height(node.left), height(node.right));
}DFS recipe: base case, trust both calls, combine.
- BFS level order
- Queue; take
sizefirst, one level a round - BST
- Inorder is sorted. Search, insert, delete O(h)
- LCA, any tree
- Return null, the target, or the LCA
- LCA, BST
- Step toward both values until they split
Watch out: Validate a BST with min/max bounds: the rule covers the whole subtree. A skewed BST has h = n.
Heaps, greedy and intervalsLesson 46 →
- Min-heap: children of
iare2i+1,2i+2. Push, pop O(log n), peek O(1). Top k: heap of size k, O(n log k). - Greedy needs a proof (exchange argument). Coins 1, 3, 4, amount 6: greedy 4+1+1, best 3+3. Use DP.
intervals.sort((a, b) => a[0] - b[0]);
const out = [intervals[0]];
for (const [s, e] of intervals.slice(1)) {
const last = out[out.length - 1];
if (s <= last[1])
last[1] = Math.max(last[1], e);
else out.push([s, e]);
}Tip: Touching ranges merge (<=); back-to-back meetings do not clash (<). Fewest to remove: sort by end.
Graphs and gridsLesson 50 →
| Need | Tool | Time |
|---|---|---|
| Fewest edges, equal costs | BFS | O(V + E) |
| Weights, none negative | Dijkstra + heap | O((V + E) log V) |
| Negative or at most k edges | Bellman–Ford | O(V × E) |
| Prerequisites, find a cycle | Kahn topological sort | O(V + E) |
| Are a and b connected? | Union-find | about O(1) each |
const q = [start];
const seen = new Set([start]);
for (let h = 0; h < q.length; h++) {
for (const nb of adj[q[h]]) {
if (seen.has(nb)) continue;
seen.add(nb); // mark on enqueue
q.push(nb);
}
}- Adjacency list O(V + E) is the default; matrix is O(V²). Undirected edges go both ways.
- Grid:
DIRSplus a bounds check. Build rows withArray.from, notfill(row). Rotate 90°: transpose, reverse rows.
Dynamic programmingLesson 55 →
- Say it: "
dp[i]means …". No sentence, no solution. - Base cases. Transition: what was the last decision?
- Order: inputs ready first. Memo is top-down, table bottom-up.
| Problem | Transition |
|---|---|
| House robber | max(skip, rob + best two back) |
| Grid paths | up + left |
| LCS | match: diagonal + 1; else max(up, left) |
| 0/1 knapsack, one row | loop capacity high to low |
const dp = Array(amount + 1)
.fill(Infinity);
dp[0] = 0;
for (let a = 1; a <= amount; a++)
for (const c of coins)
if (c <= a && dp[a - c] + 1 < dp[a])
dp[a] = dp[a - c] + 1;Answer is -1 when dp[amount] is still Infinity.
Spot the pattern, then interviewLesson 60 →
| The wording says | Technique |
|---|---|
| Sorted, pair, palindrome | Two pointers |
| Longest or shortest subarray | Variable window |
| Range sum, subarray sums to k | Prefix sums + Map |
| Seen before? count? group? | Map or Set |
| Minimum x that works | Binary search on the answer |
| All subsets, arrangements | Backtracking |
| Prefix lookups | Trie, O(L) |
| Single number, power of two | XOR, n & (n - 1) |
| Count ways, min cost | DP |
- Clarify. Examples and edge cases aloud.
- Brute force first, then find the wasted work.
- Code, then dry run a normal and an edge case.
- Say time and space unprompted.
A cheat sheet is a reminder, not a teacher. Each card links to the lesson that explains it step by step.