0% found this document useful (0 votes)
2 views12 pages

Dsa Reference Guide

The DSA Reference Guide provides a structured overview of data structures and algorithms, detailing their definitions, use cases, trade-offs, and optimal versus brute force approaches. It covers foundational concepts, searching and sorting techniques, recursion, backtracking, stacks, queues, linear structures, graph algorithms, trees, and dynamic programming. Each section emphasizes the importance of understanding when to apply specific techniques for efficient problem-solving.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views12 pages

Dsa Reference Guide

The DSA Reference Guide provides a structured overview of data structures and algorithms, detailing their definitions, use cases, trade-offs, and optimal versus brute force approaches. It covers foundational concepts, searching and sorting techniques, recursion, backtracking, stacks, queues, linear structures, graph algorithms, trees, and dynamic programming. Each section emphasizes the importance of understanding when to apply specific techniques for efficient problem-solving.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

DSA Reference Guide: What, When, Where, Why, How

Organized by how topics actually build on each other, not the order requested. Each entry:
what it is → when/where to use it → why (trade-off it solves) → how it works → brute force
vs optimal.

1. Foundations

When to Why (trade- Brute


Topic What Optimal
use off) force

Need
O(1)
Fast read, Access
index
Contiguous fixed- slow O(1),
Array access, —
index storage insert/delete in insert/delete
cache-
middle O(n)
friendly
iteration

Need
O(1) Linear
O(1) avg
average Trades scan
Hashing / Key→value via hash lookup, O(n)
lookup, order/memory O(n)
HashMap function worst
frequency for speed per
(collisions)
counts, lookup
dedup

Unsorted O(n) —
Linear data, Simple, no already
Scan every element O(n)
Search one-off preprocessing optimal for
search unsorted

Subsets,
toggling
flags, Extreme O(1) per op,
Operate on binary
Bit parity, speed/memory O(2^n) for
representation —
Manipulation space- savings, less subset
(AND/OR/XOR/shift)
optimized readable enumeration
state (DP
masks)
Array: [10][20][30][40] index→value O(1)
HashMap: key → hash(key) → bucket → value avg O(1)
Bitmask: 101101 (bit i = 1 means item i is "in")

Why hashing over array search: array needs O(n) scan unless sorted+binary search (O(log
n)); hashmap gives O(1) avg but no ordering and uses more memory.

2. Searching, Sorting, and the “Window” Family

Topic What When Brute force Optimal Space

Pre-step
O(n)
for binary
Arrange elements Bubble/selection Merge/Quick/Heap or
Sorting search, two
by order O(n²) sort O(n log n) O(log
pointers,
n)
greedy

Sorted
array, or
Halve search
“find
Binary space on
boundary” Linear scan O(n) O(log n) O(1)
Search sorted/monotonic
on
data
monotonic
predicate

Repeated
Prefix Precompute Recompute sum Build O(n), query
range-sum O(n)
Sum cumulative sums each query O(n) O(1)
queries

Contiguous
Maintain a moving subarray
Check all
Sliding subarray/substring problems O(n) (window O(1)–
subarrays O(n²)
Window with two (max sum, grows/shrinks) O(k)
or O(n³)
boundaries longest
substring)

Sorted
Two indices
array pair-
Two moving Nested loop
sum, O(n) O(1)
Pointers toward/away each O(n²)
partitioning,
other
merging

Sliding Window: [a b c d e f]
^-----^ shrink/grow window, never re-scan from start

Two Pointers: [1 3 5 7 9 11], target=12


L→ ←R move based on sum vs target

Why binary search needs sorted/monotonic data: the halving logic only works if “less than
target” is contiguous on one side — that’s the actual prerequisite, not “sorted array” specifically
(works on any monotonic predicate, e.g. “can we finish in X days?”).

3. Recursion & Backtracking

Brute
Topic What When Why force vs
optimal

Cleaner
code for
Each call
Function self-
Tree/graph traversal, divide & O(1) extra
calls itself similar
Recursion conquer, naturally recursive work but
on smaller problems,
structure stack
subproblem costs call-
O(depth)
stack
space

Explores
Recursion +
only valid
undo move
Generate all paths via Generate-
if it fails
permutations/combinations/subsets, pruning vs all-then-
Backtracking constraints
constraint satisfaction (N-Queens, generating filter
(DFS over
Sudoku) everything O(2ⁿ·n)
decision
then
tree)
filtering

Backtracking tree (subsets of {1,2}):


[]
/ \
[1] []
/ \ / \
[1,2] [1] [2] []
choose → explore → un-choose

Why backtracking over plain recursion: plain recursion explores everything; backtracking
adds the “undo + prune” step so invalid branches die early — same asymptotic worst case, but
real-world speedup.

4. Stacks, Queues & Linear Structures

Brute
Topic What When Why Optimal
force

Matching Constant
Stack
Push/pop one end brackets, undo, time both — O(1) push/pop
(LIFO)
DFS iterative ends

Frequent O(1)
insert/delete, insert/delete Insert/delete
Linked
Nodes with pointers unknown size, (given — O(1), access
List
no random node), O(n) O(n)
access needed access

Next
O(n) — each
Greater/Smaller Avoids O(n²) O(n²)
Monotonic Stack kept element
Element, pairwise nested
Stack increasing/decreasing pushed/popped
histogram max comparison loop
once
area

Recompute
Monotonic Deque kept
Sliding window max each
Queue monotonic, supports O(n·k) O(n)
max/min window
(Deque) both-end pop
O(n·k)

Need push/pop
from both ends
Deque Double-ended queue — — O(1) both ends
(BFS+window
combos)

Always- Sort
Kth largest,
Heap sorted- each Insert/extract
Binary tree, parent ≤/ scheduling,
(Priority min/max time O(log n), peek
≥ children Dijkstra, merge
Queue) without full O(n O(1)
k lists
sort log n)

Monotonic stack (Next Greater Element), arr=[2,1,5,3]:


i=0: push 2 stack:[2]
i=1: push 1 stack:[2,1]
i=2: 5>1,5>2 → pop both, NGE(1)=5, NGE(2)=5; push 5 stack:[5]
i=3: push 3 stack:[5,3]
→ each element pushed/popped at most once = O(n)

Why monotonic structures over brute force: naive “next greater element” checks every pair
(O(n²)); the monotonic stack guarantees each element is pushed and popped exactly once, so
total work is O(n) — the trade-off is needing to reason about when to pop, which is less
intuitive.

5. Array/Sequence Patterns & Math

Brute
Topic What When Optimal
force

Track running max Check all


Kadane’s
subarray sum, reset Max subarray sum subarrays O(n)
Algorithm
if negative O(n²)/O(n³)

Meeting rooms, Compare


Merge/insert/overlap Sort + sweep O(n
Intervals merge intervals, all pairs
on (start,end) pairs log n)
calendar conflicts O(n²)

Sort events by Interval overlap


Sweep coordinate, process counts, skyline O(n²)
O(n log n)
Line left→right with problem, closest pairwise
active-set pair variants

GCD/LCM, primes Divisibility, Trial


Math & Sieve O(n log log
(Sieve of combinatorics, division
Number n) for range of
Eratosthenes), cryptography- O(√n) per
Theory primes
modular arithmetic flavored problems number

Used as a proof
Proving duplicates
If n items into m<n tool, not an
Pigeonhole must exist,
boxes, some box — algorithm — O(1)
Principle bounding search
has ≥2 reasoning
space
shortcut

Kadane's: arr = [-2,1,-3,4,-1,2,1,-5,4]


curMax: reset to arr[i] if curMax+arr[i] < arr[i]
track best seen → answer = 6 ([4,-1,2,1])

Sweep line (intervals [1,3],[2,6],[8,10]):


events: (1,+1)(2,+1)(3,-1)(6,-1)(8,+1)(10,-1)
sort by time → sweep, maintain active count
6. Graphs

6a. Traversal & Building Blocks

Topic What When Complexity

Level-by-level via Shortest path (unweighted),


BFS O(V+E)
queue level order

Go deep via Connectivity, cycle detection,


DFS O(V+E)
stack/recursion topological sort base

Tree Traversal Serialize tree, BST validation,


Visit order on trees O(n)
(pre/in/post/level) expression eval

Disjoint Set
Track connected Cycle detection (undirected),
Union Naive find
components with Kruskal’s MST, dynamic
(DSU/Union- O(n)
union+find connectivity
Find)

BFS-based topological
Kahn’s DAG ordering, detect cycles
sort using in-degree O(V+E)
Algorithm in directed graph
counting

DFS-based or
Linear order respecting Build systems, course
Topological Sort Kahn’s, both
dependencies prerequisites
O(V+E)

BFS: level 0: [A]


level 1: [B,C] queue-based, guarantees shortest hops
level 2: [D,E,F]

DFS: A→B→D (backtrack)→E (backtrack)→C→F stack/recursion-based, goes deep first

BFS vs DFS trade-off: BFS guarantees shortest path in unweighted graphs but uses more
memory (stores whole frontier); DFS uses less memory (O(depth)) but doesn’t guarantee
shortest path.

6b. Shortest Path / Spanning Tree / Connectivity

When to
Algorithm Handles Complexity vs alternative
prefer
Single-source Default O((V+E) log Faster than
Dijkstra shortest path, weighted V) with Bellman-Ford if
non-negative shortest-path heap no negative
weights edges

Single-source,
handles Negative Slower but more
Bellman-Ford negative edges O(V·E) general than
weights, detects present Dijkstra
negative cycles

Need Worse than


distance running Dijkstra
All-pairs between V times (O(V·E
Floyd-Warshall O(V³)
shortest path every pair, log V)) for
small/medium sparse graphs,
V but simpler code

Similar to
MST, grow tree Dense O(E log V)
Prim’s Dijkstra
from a vertex graphs with heap
structurally

Sparse Prefer over


MST, sort edges
Kruskal’s graphs, edge O(E log E) Prim’s when
+ DSU
list given edges ≪ V²

Strongly
Condensation
SCC connected
graph, cycle O(V+E)
(Tarjan’s/Kosaraju’s) components in
grouping
directed graph

Binary lifting:
Naive: walk
Tree distance O(log n) per
LCA (Lowest Closest shared up
queries, query after O(n
Common Ancestor) ancestor in tree O(depth)
binary lifting log n)
per query
preprocess

Dijkstra: relax edges via min-heap, always finalize closest unvisited node
Bellman-Ford: relax ALL edges, V-1 times — slower, but tolerates negative weights
Floyd-Warshall: dp[i][j] = min(dp[i][j], dp[i][k]+dp[k][j]) for every k — O(V³)

Why Kruskal’s over Prim’s (or vice versa): Kruskal’s sorts edges and uses DSU — good when
graph is sparse (E close to V). Prim’s grows from a seed vertex using a heap — better for dense
graphs since it doesn’t need to sort all edges upfront.
7. Trees & Divide and Conquer

Topic What When Brute force Optimal

BST Left <


Ordered Balanced BST O(log
(Binary node < Array search
insert/search/delete, n); unbalanced worst
Search right O(n)
range queries case O(n)
Tree) invariant

Split →
Divide Merge sort, quick Often O(n log n) via
solve Solve naively
and sort, fast recurrence
subparts → O(n²)
Conquer exponentiation T(n)=2T(n/2)+O(n)
merge

O(n log n) typically


Make
(sort + scan) — but
locally Activity selection,
only correct when
Greedy optimal Huffman coding, Try-all (often
problem has greedy-
Algorithm choice, coin change DP/backtracking)
choice + optimal-
never (canonical systems)
substructure
reconsider
property

Trade-off — Greedy vs DP: greedy is faster (no exploring alternatives) but only works when
locally-optimal choices provably lead to a globally optimal solution; DP is slower but correct
even when greedy fails (e.g. 0/1 knapsack vs fractional knapsack).

8. Dynamic Programming

Concept What When

Memoization (top- Recursion + cache


Natural recursive structure, sparse state space
down) results

Tabulation Avoids recursion overhead/stack limits, dense


Iterative table fill
(bottom-up) state space

DP Variant Typical problem Brute force Optimal

House robber, climbing O(2ⁿ)


Linear DP O(n)
stairs recursion

Edit distance, LCS,


String DP O(2^min(m,n)) O(m·n)
palindrome partitioning
0/1 knapsack, subset
Knapsack-based
sum, partition equal O(2ⁿ) O(n·W)
DP
subset

Unique paths, min path


Grid-based DP O(2^(m+n)) O(m·n)
sum

Multiple state variables Polynomial, but watch


Multidimensional Exponential in
(e.g. items + capacity + memory (often needs
DP #states
count) rolling array)

Traveling Salesman, O(n!)


Bitmask DP O(2ⁿ·n)
assignment problems permutations

Matrix chain
Interval DP multiplication, burst O(2ⁿ) O(n³) typically
balloons

Count numbers with Enumerate all


Digit DP O(digits · states)
property up to N numbers O(N)

Max independent set on Exponential


Tree/Graph DP O(n) (post-order DFS)
tree, diameter subsets

LIS: O(n log n) w/ binary


Classical DP LIS, coin change, edit O(2ⁿ) or O(n²)
search; others O(n²) or
problems distance naive
O(n·target)

DP core idea: avoid recomputation by storing subproblem answers.


fib(5) naive recursion: fib(5) calls fib(4)+fib(3); fib(4) calls fib(3)+fib(2)...
→ fib(3) computed twice, fib(2) computed 3x, exponential blowup
fib(5) memoized: each fib(k) computed once → O(n)

Why memo vs tabulation: memoization is easier to write (mirrors recursion) and only
computes states actually needed; tabulation avoids recursion-depth limits and is usually faster
in practice (no function-call overhead) but computes every state in the table even if unneeded.

9. Strings & Specialized Data Structures

Topic What When Brute force Optimal

KMP
(Knuth- Pattern matching using O(n·m)
Morris- prefix-function to avoid Substring search naive O(n+m)
Pratt) re-scanning

String
Multiple pattern
Hashing Rolling hash to compare O(n+m)
search, substring O(n·m)
(Rabin- substrings in O(1) average
equality checks
Karp)

Search
Autocomplete, prefix O(L) per
each word
Trie Prefix tree of characters search, dictionary word (L =
O(n) per
lookup word length)
word

Array +
Fenwick Tree-encoded prefix Frequent updates + Update &
recompute
Tree sums, point update + range sum/count query O(log
O(n) per
(BIT) range query queries n)
query

Tree over array


Range min/max/sum Recompute Build O(n),
Segment segments, supports
with updates, more O(n) per query/update
Tree range query + range
flexible than BIT query O(log n)
update

Also used ~O(1)


DSU /
standalone: counting amortized
Union- (see graphs section) —
components, with
Find
Kruskal’s optimizations

Trie for {cat, car, dog}:


root
/ \
c d
a o
/ \ \
t r g
(cat)(car) (dog)

Fenwick vs Segment Tree:


Fenwick: simpler, less memory, only prefix-sum-style queries
Segment Tree: more general (min/max/gcd/custom), supports range updates w/ lazy propagation

Fenwick vs Segment Tree trade-off: BIT is simpler and faster to code/lower constant factor,
but only naturally supports associative+invertible operations (sums). Segment tree handles
arbitrary range queries (min, max, gcd) and range updates via lazy propagation, at the cost of
more code and memory.
10. Quick Decision Guide (“which tool do I reach for?”)

Signal in the problem Likely tool

Sliding window, Kadane’s, prefix


“contiguous subarray/substring”
sum

“sorted array” / “find boundary” Binary search, two pointers

“all permutations/combinations/subsets” Backtracking

“next greater/smaller element” Monotonic stack

“max/min in every window” Monotonic deque

“shortest path, unweighted” BFS

“shortest path, weighted, no negatives” Dijkstra

“shortest path, negative weights” Bellman-Ford

“all-pairs shortest path, small graph” Floyd-Warshall

Prim’s (dense) / Kruskal’s


“minimum spanning tree”
(sparse)

“connected components / cycle in undirected graph” DSU

“task ordering with dependencies” Topological sort (Kahn’s or DFS)

“count ways / min cost with choices + overlapping


DP
subproblems”

“locally optimal = globally optimal” Greedy

“frequent prefix-sum updates” Fenwick tree

“range query needing min/max/custom + updates” Segment tree

“prefix/autocomplete search” Trie

“substring search” KMP / Rabin-Karp

“n items, m<n boxes → must repeat” Pigeonhole principle


11. Complexity Cheat Sheet (best/typical case)

Class Examples Big-O

O(1) Hashmap lookup, array access, DSU find (amortized) constant

O(log n) Binary search, heap insert, BIT/segment tree ops logarithmic

O(n) Linear scan, sliding window, Kadane’s, BFS/DFS (per edge sum) linear

O(n log
Sorting, Dijkstra (heap), merge sort, Kruskal’s linearithmic
n)

Naive pairwise comparison, simple DP tables, Floyd-Warshall is


O(n²) quadratic/cubic
O(V³)

O(2ⁿ) Brute-force subsets, naive recursion without memoization exponential

O(n!) Brute-force permutations (TSP without DP) factorial

General pattern across this whole list: almost every “optimal” technique above is a brute-
force approach (O(n²), O(2ⁿ), O(n!)) plus one structural insight — sorting, a hash table, a
monotonic invariant, memoization, or a tree-shaped index — that eliminates redundant work.
When stuck, ask: “what am I recomputing that I could cache, presort, or maintain
incrementally?”

You might also like