Data Structure & Algorithm
Students will learn how to organize data, design efficient algorithms, analyze time complexity, and solve problems using common data structures and algorithmic techniques.
Enrolment key needed
This course is open to anyone with the key. Enter it once and this browser stays enrolled.
75 lessons · 2 hr 36 min of reading
Introduction to Data Structures and Algorithms
What these things are, why the choice between them decides how your program scales, and how to study them without drowning.
5 lessons-
🔒
What a data structure actually is
A layout for data, plus the operations that layout makes cheap.
-
🔒
What makes something an algorithm
Correctness, termination, and a cost you can predict before you run it.
-
🔒
How to choose a data structure
Start from the operations your code performs most, not from the structure you like.
-
🔒
Abstract data types versus implementations
A stack is a contract; an array and a linked list are two ways to honour it.
-
🔒
How to study this material without drowning
A repeatable loop that beats reading solutions and hoping they stick.
Time and Space Complexity (Big O Notation)
How to predict what an algorithm costs before you run it, and how to say it in the language interviewers expect.
5 lessons-
🔒
Why we count operations instead of seconds
Wall-clock time measures your laptop; growth rate measures the algorithm.
-
🔒
Reading Big O, Omega and Theta
What the notation claims, and the three rules that let you read any expression.
-
🔒
The complexity classes you will actually meet
Seven growth rates, what produces each one, and where the cliff edges are.
-
🔒
Space complexity and the cost of the call stack
Extra memory counts, and recursion spends it whether you notice or not.
-
🔒
Best, average, worst and amortised cost
Four different questions, four different answers — and why push is O(1) even when it copies.
Arrays and Strings
The structures you use every day, the costs hidden inside them, and the two patterns that solve most array questions.
5 lessons-
🔒
How arrays work in memory
Contiguous slots, O(1) indexing, and why inserting in the middle costs a shift.
-
🔒
The two pointer technique
Turn a nested loop into a single pass by walking the array from both ends, or at two speeds.
-
🔒
The sliding window technique
Reuse the work you already did instead of recomputing every subarray.
-
🔒
Prefix sums and range queries
Precompute once, then answer any range question in constant time.
-
🔒
Strings are not just arrays of characters
Immutability, encoding and the concatenation trap that turns O(n) into O(n²).
Searching Algorithms
5 lessons-
🔒
Linear search and when it is the right answer
The simplest algorithm is often the correct choice, and knowing why is the point.
-
🔒
Binary search, written correctly
Halve the search space each step — and get the boundaries right, which is the hard part.
-
🔒
Lower bound, upper bound and duplicates
The variant that answers "where does it belong?" — far more useful than plain search.
-
🔒
Binary search on the answer
When the array is not the thing you search — the range of possible answers is.
-
🔒
When searching is the wrong tool
Hashing, indexing and precomputation beat repeated searching every time.
Sorting Algorithms
The quadratic three, the two that scale, and the properties — stability, in-place, adaptivity — that decide which one production code actually uses.
5 lessons-
🔒
Bubble, selection and insertion sort
Three quadratic sorts, and the one of them that is genuinely useful.
-
🔒
Merge sort and divide and conquer
Split, sort each half, merge — O(n log n) guaranteed, stable, and the model for divide and conquer.
-
🔒
Quicksort and the pivot problem
Fastest in practice, quadratic if you choose the pivot badly.
-
🔒
Stability, in-place, and choosing a sort
The properties that decide which sort a library ships, and the comparator bugs that bite everyone.
-
🔒
Quickselect and finding the k-th element
You rarely need the whole array sorted — selecting the k-th takes O(n) on average.
Recursion and Backtracking
Writing functions that call themselves without losing control, and the systematic search that solves puzzles, permutations and constraint problems.
5 lessons-
🔒
Recursion patterns and the recursion tree
Linear, binary and multi-branch recursion — and how to read their cost off the tree.
-
🔒
The backtracking template
Choose, explore, un-choose — one skeleton that solves permutations, subsets and combinations.
-
🔒
Pruning — making exponential search finish
Cut branches that cannot lead to an answer, and an impossible search becomes practical.
-
🔒
Converting recursion to iteration
When the stack limit is a real risk, move the stack into your own hands.
-
🔒
Pruning — making exponential search finish
Cut branches that cannot lead to an answer, and an impossible search becomes practical.
Linked Lists
Nodes joined by pointers — the pointer discipline they demand, the problems they solve elegantly, and the ones where an array is simply better.
5 lessons-
🔒
Singly linked lists and pointer discipline
O(1) insertion anywhere you already stand, O(n) to get anywhere at all.
-
🔒
Reversing a linked list
The three-pointer dance, in a loop and in recursion — and why it is asked so often.
-
🔒
Fast and slow pointers
Two pointers at different speeds find the middle, detect a cycle, and locate where it starts.
-
🔒
Doubly and circular linked lists
A backward pointer buys O(1) removal; joining the ends buys endless rotation.
-
🔒
Building an LRU cache
A hash map and a doubly linked list, working together for O(1) reads and writes.
Stacks and Queues
Two restricted structures whose limitations are exactly what make them useful — plus the monotonic stack and deque patterns built on them.
5 lessons-
🔒
Stacks and the last-in first-out rule
One end, three operations, and a surprising number of problems that dissolve because of it.
-
🔒
The monotonic stack
Keep the stack sorted as you go, and "next greater element" falls out in one pass.
-
🔒
Queues and circular buffers
First in, first out — and why `shift()` on an array is the wrong way to build one.
-
🔒
Deques and the sliding window maximum
A double-ended queue turns a repeated maximum into a single pass.
-
🔒
Implementing a queue with stacks, and back again
The classic exercise, and the amortised argument that makes the answer O(1).
Hash Tables and Hashing
The structure behind O(1) lookup — how it works, how it degrades, and the problem-solving patterns it unlocks.
5 lessons-
🔒
How a hash table works
A function turns a key into an index, and an array does the rest.
-
🔒
Collisions and how tables survive them
Two keys, one slot — chaining, open addressing, and the attack that exploits both.
-
🔒
Problem-solving patterns with hash maps
Frequency counting, complement lookup and grouping by key — three patterns that cover most map questions.
-
🔒
Sets, deduplication and set algebra
Membership without values, and the operations that make intersections cheap.
-
🔒
Designing a good key
The hard part of hashing is not the function — it is deciding what counts as the same thing.
Trees and Binary Search Trees
Hierarchies, the four traversals, the ordering property that makes search logarithmic, and what happens when a tree loses its balance.
5 lessons-
🔒
Trees, height and the vocabulary you need
The words interviewers use, and why height is the number that governs every cost.
-
🔒
The four tree traversals
Preorder, inorder, postorder and level order — and which question each one answers.
-
🔒
Binary search trees
One ordering rule gives you search, insert and delete in O(h) — plus sorted iteration for free.
-
🔒
Why trees need balancing
Sorted input turns a BST into a linked list — and the structures invented to stop it.
-
🔒
Tree problem patterns
Three recursive shapes that solve most tree questions you will be asked.
Heaps and Priority Queues
The structure that always knows its smallest element — stored in a plain array, and behind top-k, scheduling and Dijkstra.
5 lessons-
🔒
What a heap is, and why it lives in an array
A weaker ordering than a BST, and index arithmetic instead of pointers.
-
🔒
Implementing a binary heap
Sift up, sift down — two loops that are the whole data structure.
-
🔒
Priority queues in practice
A queue served by importance — and the tie-breaking and starvation problems that come with it.
-
🔒
Top k, medians and streaming data
A bounded heap answers questions about huge inputs in small memory.
-
🔒
Heapsort and other heap variants
Sorting with a heap in O(1) space, and the heaps that exist beyond the binary one.
Graphs and Graph Traversal
Modelling networks, the two traversals everything else is built from, and the shortest-path algorithms that follow.
5 lessons-
🔒
Representing a graph
Adjacency list or matrix — the choice decides your memory and your traversal cost.
-
🔒
Breadth-first search (BFS)
Explore in rings, and get the shortest path in an unweighted graph for free.
-
🔒
Depth-first search (DFS)
Follow one path to its end before backtracking — and use the recursion to detect cycles and order dependencies.
-
🔒
Topological sort and dependency order
Order tasks so nothing runs before what it depends on — and detect the cycle that makes it impossible.
-
🔒
Weighted shortest paths — Dijkstra and friends
When edges have costs, BFS is no longer enough. Choose the algorithm by the weights.
Greedy Algorithms
Take the best-looking option now — when that is provably optimal, when it quietly is not, and how to tell the difference.
5 lessons-
🔒
What makes an algorithm greedy
One irrevocable local choice at a time — fast, simple, and wrong more often than it looks.
-
🔒
Proving a greedy choice is safe
Exchange argument, and the counterexample hunt that saves you from a wrong answer.
-
🔒
Interval problems
Sort by the right end, then sweep — the recipe for merging, scheduling and room allocation.
-
🔒
Classic greedy algorithms worth knowing
Huffman, Kruskal, Prim and the fractional knapsack — the ones with real proofs behind them.
-
🔒
When greedy fails, and what to do instead
Recognising the failure, and the escalation path from greedy to DP to search.
Dynamic Programming
Solve each subproblem once, remember the answer, and build up — from memoised recursion to tabulation to the classic problem families.
5 lessons-
🔒
What dynamic programming actually is
Recursion plus memory — and the two properties a problem must have before it works.
-
🔒
Memoisation versus tabulation
Top-down and bottom-up reach the same answer — pick by which one you can get right.
-
🔒
Designing the state and the transition
A five-step method that turns a vague optimisation problem into a recurrence.
-
🔒
The classic DP families
Six recurrences that most DP interview questions are variations of.
-
🔒
Handling a DP question under pressure
A running order that gets you to a correct answer even when the recurrence does not arrive immediately.
Practice Problems and Coding Interview Techniques
Turning everything in this course into a repeatable interview process — pattern recognition, communication, testing, and a practice plan that holds.
5 lessons-
🔒
A running order for the whole interview
Six phases that keep you moving even when the answer has not arrived.
-
🔒
Pattern recognition — reading the problem for its solution
The signals in a problem statement that name the technique before you start thinking.
-
🔒
Testing your solution before they do
The edge cases that break most submissions, and how to walk your own code convincingly.
-
🔒
A practice plan that holds
Eight weeks, pattern by pattern, with the repetition that turns solutions into recall.
-
🔒
Three problems, worked end to end
The full process applied — clarify, brute force, improve, code, test.