IAE Academy

The whole Data Structures and Algorithms formula sheet, to print

75 formulas in 7 topics, each with when to use it. Each is explained in the topic notes.

Arrays, stacks, queues and linked lists

Read the notes

1-D ARRAY ELEMENT ADDRESS

w = size of one element in bytes; L = lower bound of the index (L = 0 for a C array, giving Base + i*w); Base = address of the first element A[L].

2-D ARRAY ADDRESS (ROW-MAJOR, 0-INDEXED)

cols = number of columns. C stores 2-D arrays row-major, and these notes assume row-major unless a question says column-major. For column-major, whole columns are stored one after another: Base + (j*rows + i)*w, where rows = number of rows.

2-D ARRAY ADDRESS WITH ARBITRARY LOWER BOUNDS (ROW-MAJOR)

Array declared as A[L1..U1][L2..U2]; n_c = U2 - L2 + 1 is the number of columns; Base = address of A[L1][L2]. Column-major: Base + ((j - L2)*n_r + (i - L1))*w with n_r = U1 - L1 + 1.

LOWER-TRIANGULAR MATRIX STORED PACKED (ROW-MAJOR)

Holds for a 0-indexed n x n lower-triangular matrix (only entries with i >= j are stored) packed row by row into a 1-D array. Rows 0 to i-1 contribute 1 + 2 + ... + i = i(i+1)/2 entries. Address = Base + index*w. The packed array holds n(n+1)/2 elements.

NUMBER OF DISTINCT VALID STACK-PERMUTATION OUTPUTS OF N ELEMENTS

n distinct elements pushed in a fixed order (1, 2, ..., n) through one stack, with pushes and pops interleaved freely. C_n (the nth Catalan number) counts the distinct output sequences: C_1 = 1, C_2 = 2, C_3 = 5, C_4 = 14, C_5 = 42.

CIRCULAR QUEUE INDEX WRAPAROUND

SIZE = capacity of the underlying array. Every dequeue advances front by the same rule: front = (front + 1) mod SIZE.

FLOYD CYCLE-DETECTION MEETING PROPERTY

a = links from the head to the cycle's start node; c = number of nodes in the cycle; d = the SMALLEST number of links followed forward from the first meeting node to the cycle start (0 to c-1). Holds when both pointers start at the head and slow moves 1 and fast moves 2 links per iteration. d equals a itself only when a < c. In every case, advancing a links from the meeting node reaches the cycle start, which is why the reset-to-head method below works.

Trees, binary search trees and binary heaps

Read the notes

MAXIMUM NODES AT A GIVEN LEVEL

Root at level 0. An upper bound for any binary tree, reached exactly when level is completely filled.

MAXIMUM NODES IN A TREE OF GIVEN HEIGHT

Reached exactly by a perfect binary tree of height (every level completely filled).

MINIMUM NODES IN A TREE OF GIVEN HEIGHT

Reached by any tree with exactly one node per level: left-skewed, right-skewed or zig-zag.

HEIGHT RANGE FOR N NODES

The lower bound follows from . A complete binary tree with nodes, and so every binary heap, has height exactly .

LEAVES VERSUS NODES WITH TWO CHILDREN (ANY BINARY TREE)

Holds for every non-empty binary tree, whatever the number of one-child nodes. Here = leaves and = nodes with two children. Proof: count edges two ways. With nodes there are edges, and each edge hangs below exactly one parent, so . Subtracting gives .

FULL (STRICT) BINARY TREE: LEAVES, INTERNAL NODES, TOTAL

In a full binary tree every node has 0 or 2 children, so . With internal nodes it has leaves and nodes in all (always odd). More generally, a full -ary tree (every node has 0 or children) with internal nodes has leaves.

BST HEIGHT FOR N KEYS

The lower bound holds when the tree is complete. The upper bound is a chain, and every operation then costs in the worst case. Sorted or reverse-sorted input gives a chain, but so do other orders, such as 1, 5, 2, 4, 3. Of the insertion orders of distinct keys, exactly give height . When all insertion orders are equally likely, the expected height is .

BALANCE FACTOR

An AVL tree needs at every node, with the height of an empty subtree taken as . A node whose BF becomes or after an update must be rebalanced by rotation.

MINIMUM NODES IN AN AVL TREE OF HEIGHT H

The sparsest AVL tree of height is a root whose two subtrees are sparsest AVL trees of heights and . This gives and in closed form , where are the Fibonacci numbers. Consequently an AVL tree with nodes has height , which is . The maximum number of nodes of height is , as for any binary tree.

HEIGHT, LEAVES AND INTERNAL NODES OF AN N-ELEMENT HEAP

In the 1-indexed layout the leaves are at indices to ; in the 0-indexed layout at to . In a max-heap with distinct keys the minimum is always at a leaf, since an internal node has a smaller child, and it can be at any leaf. Finding it therefore means scanning the leaves, which is .

BUILD-HEAP RUNNING TIME

Bottom-up build-heap calls sift-down (heapify) on every internal node, from the last one back to the root. An -element heap has at most nodes at height , and sifting one down costs . The total is , because . It is linear, NOT . Building by successive inserts instead costs in the worst case.

HEAP SORT

Build a max-heap in . Then times: swap the root with the last element of the heap, shrink the heap by 1 and sift down the new root, each costing . It sorts in place and is not stable. auxiliary space assumes an iterative sift-down; the recursive maxHeapify below uses stack space.

CATALAN NUMBER

The recurrence chooses the root's left subtree size ; the right subtree then has nodes. The first values are . is the number of binary tree shapes with nodes and the number of BSTs on distinct keys. It also counts the ways to fully parenthesise a product of factors, and the balanced bracket strings of length . If distinct labels may be placed freely in the nodes (no BST rule), the number of labelled binary trees is .

Asymptotic complexity and recurrences

Read the notes

BIG-O (UPPER BOUND)

grows no faster than , up to a constant factor.

BIG-OMEGA (LOWER BOUND)

grows at least as fast as , up to a constant factor.

BIG-THETA (TIGHT BOUND)

and grow at the same rate. Equivalently, and both hold.

CHANGE OF BASE FOR LOGARITHMS

The two logarithms differ only by the constant factor , which is why the base is irrelevant inside , and .

LOG VS POLYNOMIAL VS EXPONENTIAL VS FACTORIAL

These three limits give the dominance rules:

  • Any positive power of beats any power of .
  • Any exponential with base greater than 1 beats any fixed power of .
  • beats any exponential with a constant base.

STIRLING'S APPROXIMATION AND LOG(N!)

Consequences:

  • and .
  • The elementary bounds are enough on their own to give .
  • This result is behind the lower bound on the number of comparisons for comparison-based sorting: a decision tree with leaves has height at least .

EXPONENT-LOG SWAP IDENTITY

Take of both sides: each becomes . Examples: , , , .

ARITHMETIC SERIES

This is the count when the inner loop runs exactly times as goes from 1 to . If the inner loop runs times, the exact count changes to , and times gives . Both are still when .

SUMS OF POWERS

This applies to triple loops such as from 1 to , from 1 to , from 1 to , and to inner loops that run times.

GEOMETRIC SERIES

When , the sum is . When , it is .

HARMONIC SERIES AND LOG(N!)

The harmonic sum appears when an inner loop steps by the outer index (inner count about ). The sum appears when an inner loop runs times.

MULTIPLICATIVE (LOGARITHMIC) LOOP

This is the exact count for for (i = 1; i <= n; i *= c). For example, with and the loop runs times, not 10.

MASTER THEOREM: GENERAL FORM

is the number of subproblems, is the factor by which the size shrinks, and is the work done outside the recursive calls (dividing plus combining). Compare with , which is the number of leaves of the recursion tree.

MASTER THEOREM FOR POLYNOMIAL F(N)

This is the special case with a constant. It is the quickest form to apply when has no log factor.

Searching, sorting and hashing

Read the notes

LINEAR SEARCH: NUMBER OF KEY COMPARISONS

The successful-search average assumes the key is present and equally likely to be at each of the positions. Both the worst case and the average case are .

BINARY SEARCH COMPLEXITY

Convention: each probe of a[mid] counts as one (three-way) comparison. The worst case holds for both successful and unsuccessful search. If a question counts the == test and the < test as separate comparisons, recount under its rule. Valid only for a sorted array with random access.

FINDING THE MINIMUM AND MAXIMUM TOGETHER

Method: take the elements in pairs. Compare the two elements of each pair with each other, then the smaller with the current minimum and the larger with the current maximum. That is 3 comparisons per pair instead of 4. Finding only the maximum (or only the minimum) takes exactly comparisons. Both counts are the best possible for comparison-based algorithms.

LOWER BOUND FOR COMPARISON-BASED SORTING

Any sort that learns about the keys only by comparing pairs of them must make comparisons in the worst case, and also on average. Proof idea: there are possible orderings of distinct keys. A binary decision tree that distinguishes them all has at least leaves, so its height is at least , and by Stirling's approximation.

NUMBER OF INVERSIONS

The maximum occurs for reverse-sorted input. The expected value is for a uniformly random permutation of distinct keys, since each of the pairs is inverted with probability . Insertion sort runs in time, so it is fast on nearly sorted input.

BALANCED DIVIDE-AND-CONQUER RECURRENCE (MERGE SORT)

This applies whenever a problem of size is split into 2 equal halves with linear combine cost. The recursion tree has levels, each costing in total.

QUICKSORT RECURRENCES

Even a lopsided but constant-fraction split, such as 1 : 9, gives . Only a split that leaves a constant number of elements on one side at every level gives .

COMPARISONS TO MERGE TWO SORTED LISTS

This is for the standard two-pointer merge of sorted lists of sizes and . The worst case occurs when the lists interleave. The best case occurs when every element of the shorter list is smaller than every element of the longer one.

BINARY HEAP OPERATION COSTS (HEAP OF N ELEMENTS)

Bottom-up build-heap is , not , because most nodes sit near the bottom and sift down only a short distance. Heap sort is build-heap followed by extract-max operations: .

COUNTING SORT COMPLEXITY

= number of elements; the keys are integers in . The sort is linear when and degrades when is much larger than . It is stable when the output is filled by scanning the input from right to left, as below. It is not in-place.

RADIX SORT COMPLEXITY

= number of digits (passes) and = the range of one digit ( for decimal digits, for bits). Least-significant-digit radix sort applies a stable sort, usually counting sort, once per digit. The total is linear when is a constant and . It is not in-place.

LOAD FACTOR

= number of keys stored, = number of slots. With chaining, can exceed 1. With open addressing every key needs its own slot, so . The open-addressing formulas below need , i.e. at least one free slot.

EXPECTED PROBES: SEPARATE CHAINING (SIMPLE UNIFORM HASHING, NEW KEYS INSERTED AT THE HEAD OF THEIR CHAIN)

These count the keys examined. An unsuccessful search walks the whole chain, whose expected length is . A successful search examines the target plus the keys inserted into the same chain after it. Including the hash computation, both searches take time. In the worst case, when all keys hash to one slot, a search takes .

EXPECTED PROBES: OPEN ADDRESSING UNDER UNIFORM HASHING (EVERY PROBE SEQUENCE EQUALLY LIKELY)

These are upper bounds, valid for . Uniform hashing is an idealisation that double hashing approximates well. Linear and quadratic probing do worse because of clustering.

EXPECTED PROBES: LINEAR PROBING (APPROXIMATIONS FOR LARGE TABLES)

Valid for . The squared term in the unsuccessful case shows how quickly primary clustering hurts as the table fills up.

Greedy, dynamic programming and divide-and-conquer

Read the notes

FRACTIONAL KNAPSACK

Applies only when any fraction of an item may be taken. Solved by sorting items on in descending order and filling greedily until capacity is used up; only the last item taken can be partial. Time .

EXPECTED (AVERAGE) CODE LENGTH

is the probability of symbol . If frequencies are given, divide each by the total frequency. is its codeword length (the depth of its leaf). Huffman's construction minimises over all prefix-free codes for the given distribution. When weights tie, different trees are possible, but they all have the same minimum .

DIVIDE-AND-CONQUER RECURRENCE (GENERAL FORM)

a = number of subproblems, n/b = size of each subproblem, f(n) = cost of the divide and combine steps outside the recursive calls.

MERGE SORT RECURRENCE

The same bound holds in the best, average and worst cases, because the split does not depend on the input order. Merging needs extra space (standard merge sort is not in-place). Merge sort is stable.

QUICKSORT RECURRENCES

The worst case happens when the pivot is always the smallest or largest element, giving (n−1, 0) splits. Example: an already sorted or reverse-sorted array with the first or last element as pivot. The best case is a perfectly balanced split. Any split in a fixed proportion (e.g. 1:9) still gives . The average case (random pivot, or all input orders equally likely) is also . Partitioning needs no auxiliary array, but the recursion stack uses space on average and in the worst case. Quicksort is not stable.

BINARY SEARCH RECURRENCE

Requires a sorted array (or a search space that is monotonic in the property being tested). The iterative version uses extra space and the recursive one stack. Inside the base of the logarithm does not matter; when an exact count is needed, use base 2.

MAX-SUBARRAY D&C RECURRENCE

This is the divide-and-conquer bound. Kadane's algorithm solves the same problem in with a single linear scan (a DP-style running "best sum ending here"). That is asymptotically better, and optimal, since every element must be read.

KADANE'S RECURRENCE

The answer is . It runs in time with extra space. With non-empty subarrays, an all-negative array returns its largest element.

LCS RECURRENCE

Indices are 1-based here: is the i-th character of X and the j-th of Y. The table is , and time and space are both . If only the length is needed, not the subsequence itself, two rows are enough, giving space.

EDIT DISTANCE RECURRENCE

In the last case the three terms are delete , insert and substitute. means deleting all i characters of X's prefix; means inserting all j characters. The table is , filled in time. If only insertions and deletions are allowed, a match still copies , but a mismatch gives . That distance equals .

0/1 KNAPSACK RECURRENCE

= best value using the first i items with capacity c. The table is , filled in time. This is pseudo-polynomial: polynomial in the numeric value of W, but exponential in the number of bits needed to write W. The DP is therefore efficient for small integer W, while 0/1 knapsack in general is NP-hard. Space can be reduced to with one array, if c runs from W down to for each item.

SUBSET SUM RECURRENCE

is true if and only if some subset of the first i numbers sums exactly to t. Base cases: and for . The table has Boolean entries, filled in time, which is also pseudo-polynomial.

MATRIX CHAIN MULTIPLICATION RECURRENCE

is the minimum cost of multiplying ; a single matrix costs nothing. Fill by increasing chain length from 2 up to n. The answer is , the last cell filled. Time (indices i, j and split k), space .

Graphs: traversals, minimum spanning trees and shortest paths

Read the notes

SPACE COST OF THE TWO REPRESENTATIONS

Use the matrix when the graph is dense (E close to V^2) or constant-time edge checks are needed; use the list when the graph is sparse (E much smaller than V^2). An undirected graph's adjacency lists hold 2E entries in total (each edge appears in both endpoints' lists); a directed graph's hold E.

HANDSHAKE LEMMA AND EDGE BOUNDS (SIMPLE GRAPHS)

The degree sum counts every undirected edge once from each end. Consequence: every undirected graph has an even number of odd-degree vertices. In a directed graph, the sum of in-degrees = the sum of out-degrees = E.

PARENTHESIS THEOREM (FOR TWO VERTICES WITH D[U] < D[V])

Exactly one of the two holds. The first means v is a descendant of u in the DFS forest (the intervals are nested). The second means neither is a descendant of the other (the intervals are disjoint). Partial overlap, d[u] < d[v] < f[u] < f[v], is impossible.

NUMBER OF EDGES IN A SPANNING TREE OR FOREST

The first holds for any spanning tree of a connected graph on V vertices, whatever the weights. The second is for a graph with k connected components, where Kruskal run to completion produces a minimum spanning forest.

NUMBER OF LABELLED SPANNING TREES OF THE COMPLETE GRAPH K_N

For example, K_4 has 4^2 = 16 spanning trees. This counts spanning trees, not MSTs; with distinct weights, exactly one of them is the MST.

DIJKSTRA'S TIME COMPLEXITY

Correctness is guaranteed only when all edge weights are non-negative. The array version suits dense graphs (E close to V^2); the binary-heap version suits sparse graphs (E much smaller than V^2).

BELLMAN-FORD'S TIME COMPLEXITY

Each of the V−1 rounds scans all E edges once; the extra negative-cycle check costs another O(E).

FLOYD-WARSHALL RECURRENCE

d_k[i][j] is the length of the shortest path from i to j whose intermediate vertices all lie in {1,...,k}. d_0 is the input: d_0[i][i] = 0, d_0[i][j] = w(i,j) where a direct edge exists, and infinity otherwise. The answer is d_V.

FLOYD-WARSHALL COMPLEXITY

Three nested loops over all V vertices. It is correct with negative edge weights as long as there is no negative-weight cycle, and it detects one if present. Replacing min with OR and + with AND gives the transitive-closure (reachability) algorithm, also O(V^3).

Programming in Python

Read the notes

FLOOR DIVISION AND REMAINDER IN PYTHON

Holds for integers with b nonzero; a // b is the floor of the true quotient, so a nonzero remainder takes the sign of b.

NUMBER OF VALUES IN A RANGE

Holds for integers a, b and any nonzero step k, positive or negative; for example len(range(3, 20, 4)) = ceil(17/4) = 5 and len(range(5, 0, -2)) = ceil(2.5) = 3.

SET OPERATION SIZES

For finite sets; A △ B is the symmetric difference, written A ^ B in Python. Use these to count len(A | B) or len(A ^ B) without listing the elements.

NUMBER OF CALLS MADE BY NAIVE FIBONACCI RECURSION

For the fib above, which returns directly for n < 2 and otherwise calls itself on n-1 and n-2, with F(0)=0, F(1)=1. C(n) counts every call, the first one included; for example fib(6) makes C(6) = 2·13 − 1 = 25 calls.