Chapter 3: Mathematical Foundations for DSA
3.03Beginner9 topics16 min1 interactive animation

Discrete mathematics

The discrete structures behind data structures: sets, relations, functions and their types, Cartesian products, tuples, sequences, multisets and permutations.

Learning goals

  • Use set operations and relate them to Java collections
  • Classify relations and functions
  • Count products, sequences and arrangements

Prerequisites

Arithmetic essentials
3.03.1

Sets

A set is an unordered collection of distinct elements. Operations: union A ∪ B, intersection A ∩ B, difference A \ B and subset A ⊆ B. HashSet implements a set; addAll, retainAll and removeAll are union, intersection and difference.

The size of a power set (all subsets) of an n-element set is 2ⁿ, which is why subset enumeration is exponential.

Java
1Set<Integer> a = new HashSet<>(List.of(1, 2, 3)), b = new HashSet<>(List.of(2, 3, 4));
2Set<Integer> union = new HashSet<>(a); union.addAll(b); // {1, 2, 3, 4}
3Set<Integer> inter = new HashSet<>(a); inter.retainAll(b); // {2, 3}
4Set<Integer> diff = new HashSet<>(a); diff.removeAll(b); // {1}
3.03.2

Relations

A relation on a set is a set of ordered pairs. It is reflexive if every x relates to itself, symmetric if x ~ y implies y ~ x, and transitive if x ~ y and y ~ z imply x ~ z. An equivalence relation has all three and splits the set into disjoint classes, which is exactly what union-find maintains.

A partial order (reflexive, antisymmetric, transitive) underlies sorting and dependency graphs.

RelationReflexiveSymmetricTransitiveKind
= on integersyesyesyesequivalence
≤ on integersyesnoyespartial order
< on integersnonoyesstrict order
connected in a graphyesyesyesequivalence
friend of (social network)noyesnoneither
3.03.3

Functions

A function f: A → B assigns every element of A (the domain) exactly one element of B (the codomain). A Java method that returns a value and has no side effects is a function; a Map is a finite function from keys to values.

Hash functions map keys to bucket numbers; because there are more keys than buckets, collisions are unavoidable.

Java
1Function<Integer, Integer> square = x -> x * x;
2int y = square.apply(7); // 49
3Map<String, Integer> lengthOf = Map.of("cat", 3, "horse", 5); // a function on a finite domain
3.03.4

Injective/surjective/bijective

A function is injective (one-to-one) if different inputs give different outputs, surjective (onto) if every element of the codomain is hit, and bijective if both. A bijection has an inverse and means the two sets have the same size.

Perfect hashing aims for an injective hash on a known key set. Sorting is a bijection from positions to positions. A hash function from all strings to 32-bit ints cannot be injective.

FunctionInjectiveSurjective
f(x) = 2x on integersyesno (odd numbers missed)
f(x) = x² on integersno (f(2) = f(-2))no
f(x) = x + 1 on integersyesyes (bijective)
s.length() on stringsnoonto the non-negative integers
3.03.5

Cartesian product

The Cartesian product A × B is the set of all ordered pairs (a, b), with |A × B| = |A| · |B|. Nested loops enumerate it: the grid of cells in a matrix is rows × columns, and the edges of a complete directed graph are V × V.

The size multiplies, so the product of k sets with n elements each has nᵏ elements.

Java
1int[] rows = {0, 1, 2}, cols = {0, 1};
2int count = 0;
3for (int r : rows) for (int c : cols) count++; // 3 * 2 = 6 pairs
3.03.6

Tuples

A tuple is a fixed-size ordered list of values that may have different types, such as a point (x, y) or an edge (u, v, w). In Java use a record, which gives you equals and hashCode so tuples can be keys.

Order matters: (1, 2) ≠ (2, 1).

Java
1record Edge(int u, int v, int w) {}
2Edge e = new Edge(0, 3, 12);
3boolean same = e.equals(new Edge(0, 3, 12)); // true
3.03.7

Sequences

A sequence is an ordered list that may contain repeats; position matters. Arrays, lists and strings are sequences. A subsequence keeps the relative order but may skip elements, whereas a substring is contiguous. A sequence of n elements has 2ⁿ subsequences (including the empty one) but only n(n + 1)/2 non-empty substrings.

Longest common subsequence and longest increasing subsequence are classic dynamic programming problems.

Of "abc"CountExamples
Substrings (non-empty)6a, ab, abc, b, bc, c
Subsequences (including empty)8"", a, b, c, ab, ac, bc, abc
3.03.8

Multisets

A multiset (bag) is like a set that tracks how many times each element occurs. In Java use a Map<T, Integer> of counts, or a TreeMap when you need sorted keys. Anagram checks and frequency problems compare multisets.

Two strings are anagrams exactly when their multisets of letters are equal.

Java
1static Map<Character, Integer> bag(String s) {
2 Map<Character, Integer> m = new HashMap<>();
3 for (char c : s.toCharArray()) m.merge(c, 1, Integer::sum);
4 return m;
5}
6boolean anagram = bag("listen").equals(bag("silent")); // true
3.03.9

Permutations

A permutation is an ordering of items. There are n! orderings of n distinct items, and P(n, k) = n! / (n - k)! ordered selections of k of them. Brute-force search over permutations is feasible only for n up to about 10.

Choose n and k in the animation and compare the count with the list of arrangements.

Java
1static void permute(int[] a, int k, List<int[]> out) {
2 if (k == a.length) { out.add(a.clone()); return; }
3 for (int i = k; i < a.length; i++) {
4 swap(a, k, i); permute(a, k + 1, out); swap(a, k, i);
5 }
6}
7static void swap(int[] a, int i, int j) { int t = a[i]; a[i] = a[j]; a[j] = t; }

Permutations nPr and combinations nCr

Interactive · edit the input

Your input

Try

items

1
2
3
4

current choice

empty

found so far (0 of 12)

empty
Setup

Choose 2 of 4 items where order matters: n × (n-1) × … = 4! / 2! = 12.

Step 1 / 30
Java
1static void pick(int[] items, int r, boolean ordered, int start,
2 List<Integer> current, boolean[] used, List<List<Integer>> out) {
3 if (current.size() == r) { out.add(new ArrayList<>(current)); return; }
4 for (int i = ordered ? 0 : start; i < items.length; i++) {
5 if (used[i]) continue; // each item at most once
6 used[i] = true;
7 current.add(items[i]);
8 pick(items, r, ordered, i + 1, current, used, out);
9 current.remove(current.size() - 1); // backtrack
10 used[i] = false;
11 }
12}

Live state

0 arrangements

n

4

r

2

expected

12

No condition evaluated on this step
Execution trace (dry run table)Show 30 steps
StepLineStateWhat happens
1L1n=4 r=2 expected=12Choose 2 of 4 items where order matters: n × (n-1) × … = 4! / 2! = 12.
2L7picked=1 size=1 r=2Pick 1: choice 1 of 2. There were 4 options for the first slot, 3 for the second, and so on (multiplication principle).
3L7picked=2 size=2 r=2Pick 2: choice 2 of 2.
4L3found=1 expected=12Complete: 1, 2. That is arrangement #1.
5L7picked=3 size=2 r=2Pick 3: choice 2 of 2.
6L3found=2 expected=12Complete: 1, 3. That is arrangement #2.
7L7picked=4 size=2 r=2Pick 4: choice 2 of 2.
8L3found=3 expected=12Complete: 1, 4. That is arrangement #3.
9L7picked=2 size=1 r=2Pick 2: choice 1 of 2. There were 4 options for the first slot, 3 for the second, and so on (multiplication principle).
10L7picked=1 size=2 r=2Pick 1: choice 2 of 2.
11L3found=4 expected=12Complete: 2, 1. That is arrangement #4.
12L7picked=3 size=2 r=2Pick 3: choice 2 of 2.
13L3found=5 expected=12Complete: 2, 3. That is arrangement #5.
14L7picked=4 size=2 r=2Pick 4: choice 2 of 2.
15L3found=6 expected=12Complete: 2, 4. That is arrangement #6.
16L7picked=3 size=1 r=2Pick 3: choice 1 of 2. There were 4 options for the first slot, 3 for the second, and so on (multiplication principle).
17L7picked=1 size=2 r=2Pick 1: choice 2 of 2.
18L3found=7 expected=12Complete: 3, 1. That is arrangement #7.
19L7picked=2 size=2 r=2Pick 2: choice 2 of 2.
20L3found=8 expected=12Complete: 3, 2. That is arrangement #8.
21L7picked=4 size=2 r=2Pick 4: choice 2 of 2.
22L3found=9 expected=12Complete: 3, 4. That is arrangement #9.
23L7picked=4 size=1 r=2Pick 4: choice 1 of 2. There were 4 options for the first slot, 3 for the second, and so on (multiplication principle).
24L7picked=1 size=2 r=2Pick 1: choice 2 of 2.
25L3found=10 expected=12Complete: 4, 1. That is arrangement #10.
26L7picked=2 size=2 r=2Pick 2: choice 2 of 2.
27L3found=11 expected=12Complete: 4, 2. That is arrangement #11.
28L7picked=3 size=2 r=2Pick 3: choice 2 of 2.
29L3found=12 expected=12Complete: 4, 3. That is arrangement #12.
30L12found=12 formula=12 return=1212 arrangements listed, matching 4! / 2! = 12. The formula gives the count without listing them: that is the point of counting principles.

Practice ladder

Now try it yourself

Easy

  • List all subsets of {a, b, c}
  • How many cells are in a 4 × 7 grid?

Medium

  • Is “divides” on positive integers reflexive, symmetric, transitive?
  • Count the substrings and subsequences of a string of length 5

Advanced

  • Show that a hash function from 32-bit strings of length 8 to 32-bit ints cannot be injective

Key takeaways

  • Java sets and maps model mathematical sets and functions.
  • Equivalence relations split a set into classes, the idea behind union-find.
  • A product multiplies sizes, subsets give 2ⁿ, orderings give n!.