FREE COURSE / REAL PRACTICE
Data structures & algorithms
Build and use arrays, maps, trees and graphs while reasoning about complexity, traversal and algorithmic contracts.
What you’ll work toward
Select and implement data structures, test boundary cases and explain the cost of an approach.
Read an explanation, inspect the diagrams and work through the available checks, debugging exercises and builds. Feedback and prerequisite links guide the next step.
Before you start
The entry lesson has no earlier CodeRigor skill prerequisite. Start there and follow the sequence.
Individual lessons can add prerequisites. The course map shows your actual readiness.
A look inside the first lesson
#include <print>
int main() {
const int n = 1000;
long long a = 0, b = 0, c = 0, d = 0;
for (int i = 0; i < n; ++i) // n
for (int j = 0; j < n; ++j) ++a; // × n = n²
for (int i = 0; i < n; ++i) // inner runs i times:
for (int j = 0; j < i; ++j) ++b; // 0 + 1 + … + (n-1) = n(n-1)/2 → still Θ(n²)
for (int i = n; i > 0; i /= 2) ++c; // halving: ⌊log₂ n⌋ + 1 iterations → Θ(log n)
for (int i = 1; i <= n; ++i) // inner runs n/i times:
for (int j = i; j <= n; j += i) ++d; // n(1 + 1/2 + … + 1/n) ≈ n ln n → Θ(n log n)
std::println("n²={} triangle={} halving={} harmonic={}", a, b, c, d);
}Your course outline
Follow the lessons in curriculum order. Open a unit to preview the ideas you’ll work with.
Foundations
- LESSON 01.01
Big-O and measuring
Count the work a loop does, know the cost of standard operations, and measure growth honestly with a log-log slope.
Open lesson - LESSON 01.02
Binary search
Find the first position where a monotone predicate becomes true, in O(log n), with a loop invariant you can state.
Open lesson
Owning things
- LESSON 02.01
Dynamic array (your own vector)
Separate raw storage from live objects, grow geometrically for amortized O(1) push_back, and keep ownership, aliasing and exceptions straight.
Open lesson - LESSON 02.02
Stacks, queues and ring buffers
LIFO and FIFO, the standard adaptors, and a growable ring buffer with O(1) push and pop at both ends of its life.
Open lesson - LESSON 02.03
Hash maps and sets in practice
Use std::unordered_map and unordered_set for O(1)-average counting, grouping and lookup — and know their traps: operator[] inserts, order is unspecified, the hash decides your complexity.
Open lesson - LESSON 02.04
Two pointers and sliding windows
Replace nested loops with two indices that only move forward: pair sums on sorted data, in-place compaction, and windows that grow and shrink under an invariant — all in O(n).
Open lesson
Generic code
- LESSON 03.01
Linked lists
Node-based sequences: sentinels that delete edge cases, O(1) splicing, iterative reversal and teardown, fast/slow pointers — and why they lose to vectors on modern hardware.
Open lesson - LESSON 03.02
Insertion sort and merge sort
Two stable sorts with opposite strengths: insertion sort (simple, adaptive, great for small or nearly sorted input) and merge sort (O(n log n) always, O(n) extra space).
Open lesson
Hashing and heaps
- LESSON 04.01
Hash tables: open addressing
Build a flat hash map: mix the hash, probe linearly in a power-of-two array, keep the load factor bounded, and delete without breaking probe chains.
Open lesson - LESSON 04.02
Binary heaps and priority queues
Keep the largest element on top of an array-shaped tree: sift up and down in O(log n), build a heap in O(n), and use std::priority_queue without its traps.
Open lesson - LESSON 04.03
Partitioning, quicksort and selection
Partition around a pivot with a precise invariant, then build quicksort and quickselect on it — and make them survive sorted, reversed and all-equal input.
Open lesson
Compile time and trees
- LESSON 05.01
Binary trees and binary search trees
Traverse trees in every order, keep the BST invariant through insert and erase, and never let a degenerate tree overflow your stack.
Open lesson - LESSON 05.02
Recursion and backtracking
Trust the smaller problem; then search a decision tree with choose → explore → un-choose, pruning dead branches and skipping duplicate ones.
Open lesson
Sum types, contracts, graphs
- LESSON 06.01
Balanced search trees
Keep a search tree's height logarithmic with rotations: AVL balance factors, red-black colours, and why std::map is built the way it is.
Open lesson - LESSON 06.02
Graphs: representation, BFS and DFS
Store graphs so neighbours are cheap to visit, then explore them breadth-first (shortest paths, layers) and depth-first (components, cycles, colourings) without blowing the stack.
Open lesson - LESSON 06.03
Union-find (disjoint sets)
Track which elements are connected as you merge groups: a parent array, union by size and path compression give near-constant time per operation.
Open lesson
Pipelines and memory
- LESSON 07.01
Shortest paths and topological order
Dijkstra with a heap and lazy deletion, 0-1 BFS, topological order with Kahn's algorithm, and longest paths in a DAG — with 64-bit distances and cycle detection.
Open lesson - LESSON 07.02
Dynamic programming I
Turn exponential recursion into polynomial time: name the state, write the recurrence, then memoize, tabulate and shrink the table.
Open lesson - LESSON 07.03
Fixed-capacity containers: no hidden allocations
Game- and embedded-style containers in the spirit of EASTL: inline storage with an optional heap overflow, small-buffer optimisation, fixed node pools — and why a frame budget bans surprise allocations.
Open lesson
Reflection and advanced structures
- LESSON 09.01
Tries and prefix structures
Store strings as paths in a tree of characters, so prefix questions — how many words start with this, what are the first k completions — cost time proportional to the prefix, not to the dictionary.
Open lesson - LESSON 09.02
Range queries: Fenwick and segment trees
Answer range sums, minimums and friends while the data keeps changing: Fenwick trees for prefix sums, segment trees for any monoid, lazy propagation for range updates — all O(log n).
Open lesson - LESSON 09.03
String algorithms: KMP, Z and hashing
Find patterns in O(n + m) by never re-reading text you already matched: borders and the prefix function (KMP), the Z-function, periods, and rolling hashes that are verified, not trusted.
Open lesson
Performance
- LESSON 10.01
Dynamic programming II
Richer DP states — two strings, intervals, subsets as bitmasks, subtrees, DAGs and digits — plus reconstruction, rolling memory and the classic speed-ups.
Open lesson - LESSON 10.02
Intrusive and structure-of-arrays containers
Containers that don't own their elements' memory or layout: intrusive lists (the link lives in the object), sorted-vector maps, structure-of-arrays tuple vectors, segmented vectors and bit vectors — the EASTL toolbox and when each one pays.
Open lesson