Data structures and algorithms roadmap
Every stage in order, from Big-O through trees, graphs, sorting, recursion and dynamic programming, ending with the patterns that coding interviews draw on.
Core and recommended topics. Optional ones stay hidden until you have some real work behind you.
- Core: needed for most jobs of this kind
- Recommended: worth learning early
- Optional: learn it when your work needs it
Stage 1
Complexity and Big-O
Big-O notation describes how the running time or memory of an algorithm grows with the size of its input. It lets you compare approaches before running them, and it is the language the rest of this roadmap uses.
Core: Asymptotic notation
Big-O gives an upper bound, Big-Omega a lower bound and Big-Theta a tight bound. Interviewers say O when they usually mean Theta. Constants and smaller terms are dropped because they matter less as n grows.
Outside linkBig-O notation Outside linkBig-O cheat sheet SimulatorBig-O race
Core: Time and space trade-offs
Faster algorithms often use more memory. A hash map turns an O(n) scan into an O(1) lookup by using O(n) extra space. Knowing which resource you can spare guides the design.
CodexProblem-solving Outside linkBig-O cheat sheet Outside linkTime complexity
Core: Common complexity classes
O(1), O(log n), O(n), O(n log n), O(n²), O(2ⁿ) and O(n!). Learn how fast each grows. The step from O(n log n) to O(n²) is where many first attempts become too slow.
SimulatorBig-O race Outside linkBig-O cheat sheet Outside linkComputational complexity
Recommended: Amortised analysis
Growing a dynamic array costs O(n), but it happens rarely enough that appending averages O(1). Amortised cost is the average over a sequence of operations rather than the cost of the worst single one.
Outside linkAmortised analysis Outside linkAmortised analysis (CP-Algorithms) SimulatorBig-O race
Stage 2
Arrays and strings
An array stores elements next to each other in memory, so reading any index takes constant time. Strings behave like arrays of characters with a few quirks of their own. Two pointers and sliding windows, both covered here, solve a large share of interview problems.
Core: Arrays and dynamic arrays
A fixed array is one block of memory. A dynamic array (vector, list, slice) allocates a larger block and copies when it fills. Indexing is O(1); inserting in the middle is O(n) because later elements shift.
Core: Two pointers
Move one index from each end, or two at different speeds, to replace an O(n²) nested loop with one O(n) pass. Pair sums, palindrome checks and partitioning a sorted array use it.
CodexProblem-solving Outside linkTwo-pointer technique Outside linkNeetCode roadmap
Core: Sliding window
Keep a running window over a range and update it as it moves instead of recomputing. Longest-substring and fixed-size subarray problems drop from O(n·k) to O(n).
CodexProblem-solving Outside linkSliding window (NeetCode) Outside linkMaximum subarray
Recommended: Prefix sums and difference arrays
Compute running totals once and any range sum takes O(1). A difference array does the reverse for range updates. Both turn repeated range work from quadratic to linear.
Outside linkPrefix sum Outside linkPrefix sums (CP-Algorithms)
Recommended: String algorithms
KMP and Rabin-Karp find a pattern in O(n + m) instead of O(n·m). In languages with immutable strings, concatenating in a loop can be O(n²), so use a builder.
Outside linkString searching Outside linkKMP algorithm SimulatorSuffix tree
Stage 3
Hashing
A hash table gives average constant-time lookups, but collisions, resizing and a poor hash function can make it much slower. Knowing how it works tells you when that average holds.
Core: Hash functions
A good hash function is fast and spreads keys evenly across buckets. A poor one puts many keys in the same few buckets, and lookups slow to O(n).
GuideHow hash tables work Outside linkHash function Outside linkHash table
Core: Collision resolution
When two keys land in the same bucket, chaining keeps a list per bucket and open addressing probes for the next free slot. Both stay close to O(1) until the table fills up and has to resize.
GuideHow hash tables work Outside linkHash table collisions Outside linkOpen addressing
Core: Hash maps and sets in practice
The structure interviews use most. Problems such as two-sum, finding duplicates and grouping anagrams usually reduce to a hash map, using O(n) space to remove a nested loop.
CodexProblem-solving SimulatorLRU cache Outside linkMap (MDN) Outside linkdict (Python docs)
Recommended: Bloom filters
A probabilistic set that answers "definitely not present" or "probably present" using little memory. It never gives false negatives, and you choose the false-positive rate. Databases and caches use them to skip lookups that would find nothing.
SimulatorBloom filter Outside linkBloom filter GuideHow hash tables work
Stage 4
Linked lists, stacks and queues
A linked list gives up constant-time indexing in exchange for constant-time insertion at a known node, and it makes you work with pointers. Stacks (last in, first out) and queues (first in, first out) are restricted lists used in recursion, parsing and scheduling.
Core: Singly and doubly linked lists
Elements are not contiguous, so reaching index i means following i pointers. Inserting or deleting at a node you already have is O(1). Reversing a list in place is a standard interview question.
Core: Stacks
Push and pop at one end, last in, first out. The call stack, undo history, bracket matching and depth-first search all use stacks.
SimulatorQueue & stack Outside linkStack (data structure) SimulatorStack frame
Core: Queues
Add at the back and remove from the front, first in, first out. Breadth-first search, task scheduling and producer-consumer pipelines use queues. A deque allows both ends; a priority queue orders by priority.
Recommended: Ring buffers
A fixed-size queue that wraps around using head and tail indices, with no allocation per operation. Used for audio buffers, logging pipelines and lock-free handoff between threads.
GuideHow ring buffers work Outside linkCircular buffer SimulatorQueue & stack
Recommended: Fast and slow pointers
Floyd's cycle detection moves one pointer twice as fast as the other. In one pass and O(1) space it finds a cycle, the middle node, or the kth node from the end.
SimulatorLinked list Outside linkCycle detection CodexProblem-solving
Stage 5
Trees and binary search trees
Trees are where recursion becomes practical. A balanced binary search tree gives O(log n) lookups, and one built from sorted input becomes a list with O(n) lookups. Most tree problems build on the four standard traversals.
Core: Binary trees and traversals
Pre-order, in-order, post-order and level-order are four ways to visit every node, each suited to different tasks. In-order on a binary search tree gives sorted output; level-order is breadth-first search with a queue.
Core: Binary search trees
Smaller keys go left and larger keys go right, at every node. That gives O(log n) search, insert and delete while the tree is balanced. Inserting sorted data turns it into a linked list.
Core: Recursive tree problems
Height, diameter, lowest common ancestor and path sums are each a recursive definition plus a base case. Ask what each node needs to know from its children.
CodexProblem-solving SimulatorRecursion Outside linkNeetCode trees
Recommended: Tree serialisation
Convert a tree to a string and rebuild exactly the same tree from it. Doing this correctly shows you understand traversal order, and it can be done with either depth-first or breadth-first search.
CodexProblem-solving SimulatorDecision tree Outside linkTree traversal
Stage 6
Heaps and priority queues
A heap keeps the smallest (or largest) item at the root and restores that order in O(log n) after each change. Problems that ask for the k largest items, the next event, or a merge of several sorted lists usually call for one.
Core: Binary heaps
A complete binary tree stored in an array, with the children of index i at 2i+1 and 2i+2. Insert and remove-min are O(log n). There are no pointers, so it uses the CPU cache well.
SimulatorHeap Outside linkBinary heap Outside linkHeap (data structure)
Core: Priority queues
The operations a heap supports: insert with a priority and remove the highest-priority item. Dijkstra's algorithm, Huffman coding and event simulation all use one.
Core: Top-k and streaming selection
Keep a heap of size k to find the k largest items of a stream in O(n log k) without sorting everything. It is the usual answer to "top trending items" with limited memory.
CodexProblem-solving SimulatorHeap Outside linkSelection algorithm
Recommended: Heapsort and heapify
Building a heap from an array takes O(n), less than the O(n log n) people often expect. Removing the minimum n times then sorts in place in O(n log n), with no bad worst case, though quicksort is usually faster in practice.
Outside linkHeapsort SimulatorSorting visualizer SimulatorHeap
Stage 7
Balanced and specialised trees
A plain binary search tree can become unbalanced. Red-black trees and B-trees rebalance on every write to guarantee O(log n), and tries and segment trees are built for one specific kind of query.
Core: Red-black trees
A binary search tree that colours nodes and rotates on insert and delete so its height stays within twice the minimum. Many standard-library ordered maps and sets, such as C++
std::mapand Java'sTreeMap, use one.SimulatorRed-black tree Outside linkRed–black tree SimulatorBalanced tree
Core: B-trees and B+ trees
Wide, shallow trees where each node holds many keys and fills a disk page. Fewer levels means fewer disk reads, which is why most relational database indexes are B+ trees.
Core: Tries
A tree keyed on shared prefixes, so a lookup costs O(length of the key) regardless of how many keys are stored. Used for autocomplete, IP routing tables and spell checkers.
SimulatorTrie autocomplete Outside linkTrie SimulatorSuffix tree
Recommended: Segment trees and Fenwick trees
Range sums or range minimums with updates in between, each in O(log n). A prefix-sum array is faster for queries but has to be rebuilt after every update.
SimulatorSegment tree Outside linkSegment tree (CP-Algorithms) Outside linkFenwick tree
Stage 8
Graphs and traversal
When a problem involves connections, such as friendships, dependencies, roads or states, it can be modelled as a graph. Choose a representation, then use breadth-first or depth-first search; many graph problems in interviews come down to one of the two.
Core: Graph representations
An adjacency list suits sparse graphs, which most real graphs are. An adjacency matrix suits dense graphs or constant-time edge checks, at O(V²) memory.
Outside linkGraph (data structure) Outside linkAdjacency list
Core: Breadth-first search
Visit nodes level by level using a queue. On an unweighted graph the first time you reach a node is by the fewest edges, so BFS finds shortest paths. Flood fill uses it too.
SimulatorBFS & DFS traversal Outside linkBreadth-first search Outside linkVisuAlgo: graph traversal
Core: Depth-first search
Follow one path as far as it goes before backing up, using recursion or a stack. Cycle detection, connected components and topological sort all use the order in which DFS enters and leaves nodes.
SimulatorBFS & DFS traversal Outside linkDepth-first search SimulatorRecursion
Recommended: Topological sort
Order the nodes of a directed acyclic graph so every edge points forward, which gives a valid build or task order. Kahn's algorithm uses in-degrees and a queue; the DFS version uses post-order. Both detect cycles.
CodexProblem-solving Outside linkTopological sorting SimulatorBFS & DFS traversal
Recommended: Union-find
A disjoint-set structure that answers "are these two connected?" in nearly constant amortised time, using path compression and union by rank. Kruskal's algorithm depends on it.
Outside linkDisjoint-set Outside linkUnion-find (CP-Algorithms) CodexProblem-solving
Stage 9
Shortest paths and other graph algorithms
With weights on the edges, traversal becomes optimisation. Dijkstra, Bellman-Ford, A* and the max-flow algorithms each make specific assumptions about the graph and have a known cost.
Core: Dijkstra's algorithm
Shortest paths from one node when all edge weights are non-negative, using a priority queue, in O((V + E) log V). With a negative edge it can give wrong answers, which interviewers often ask about next.
SimulatorDijkstra pathfinding Outside linkDijkstra's algorithm GuideHow graph routing works
Core: A* search
Dijkstra's algorithm plus a heuristic that steers the search toward the goal. With an admissible heuristic it still finds the shortest path while exploring fewer nodes. Common in games and maps.
SimulatorA* pathfinding Outside linkA* search algorithm GuideHow graph routing works
Recommended: Bellman-Ford and negative edges
Slower than Dijkstra at O(V·E), but it handles negative edge weights and detects negative cycles. Use it when Dijkstra's assumption does not hold.
Outside linkBellman–Ford algorithm Outside linkShortest path (CP-Algorithms) GuideHow graph routing works
Recommended: Minimum spanning trees
Connect every node with the lowest total edge weight. Kruskal's algorithm sorts edges and uses union-find; Prim's grows a tree from one node with a heap.
Outside linkMinimum spanning tree Outside linkKruskal's algorithm Outside linkPrim's algorithm
Stage 10
Sorting and searching
You will rarely write a sort by hand. It still helps to know why quicksort is usually fastest, when merge sort is the better choice, and where binary search goes wrong at the boundaries.
Core: Comparison sorts
Merge sort is stable and always O(n log n) but needs extra space. Quicksort is usually fastest but has an O(n²) worst case. Heapsort sorts in place with no bad worst case. Each suits different constraints.
SimulatorSorting visualizer Outside linkSorting algorithm Outside linkVisuAlgo: sorting
Core: The O(n log n) lower bound
No sort that works only by comparing elements can do better than O(n log n) in the worst case. It is a proven limit, so if a problem needs sorted data, that cost is part of the answer.
Outside linkComparison sort SimulatorBig-O race Outside linkSorting algorithm
Core: Binary search
Halve the search range each step for O(log n) on sorted data. Off-by-one errors at the boundaries are common. Binary search on the answer applies the same idea to any yes/no condition that changes only once.
SimulatorBinary search Outside linkBinary search algorithm Outside linkBinary search (CP-Algorithms)
Recommended: Non-comparison sorts
Counting sort, radix sort and bucket sort avoid the O(n log n) limit by using the structure of the keys, and can run in O(n) when the range of values is limited.
Outside linkRadix sort Outside linkCounting sort SimulatorSorting visualizer
Stage 11
Recursion and backtracking
A recursive function solves a problem by calling itself on a smaller version, with a base case to stop. Backtracking is recursion that tries choices and undoes the ones that fail, which is how permutations, Sudoku solvers and the N-Queens puzzle work.
Core: Recursion and the call stack
Each recursive call adds a frame to the call stack, and the base case is what stops it growing until it overflows. Watching the frames build up shows that recursion is a stack managed for you.
SimulatorRecursion SimulatorStack frame Outside linkRecursion (computer science)
Core: Backtracking
Make a choice, recurse, and undo the choice if it leads nowhere. Subsets, permutations, combinations and constraint puzzles all follow the same choose, explore, undo structure.
CodexProblem-solving Outside linkBacktracking SimulatorN-Queens backtracking
Core: N-Queens and constraint search
Place N queens on an N×N board so that none attack each other. Rejecting illegal placements early cuts the search from impossibly large to fast enough.
SimulatorN-Queens backtracking Outside linkEight queens puzzle Outside linkConstraint satisfaction
Recommended: Tail recursion and loops
When the recursive call is the last thing a function does, it can be rewritten as a loop that uses no extra stack. This avoids stack overflows on deep inputs, especially in languages that do not optimise tail calls.
Outside linkTail call SimulatorRecursion SimulatorStack frame
Recommended: Memoisation
Store the result of each subproblem so it is computed once. It can turn exponential recursion into polynomial time, and it leads directly into dynamic programming.
SimulatorDP: longest common subsequence Outside linkMemoization CodexProblem-solving
Stage 12
Dynamic programming
Dynamic programming is the topic candidates find hardest. It is recursion where each subproblem is solved once and stored. The skill is spotting repeated subproblems and choosing a state that holds everything the next step needs.
Core: Memoisation and tabulation
Top-down memoisation caches recursive calls; bottom-up tabulation fills a table in order. Tabulation avoids deep recursion, and memoisation computes only the states it needs.
SimulatorDP: longest common subsequence Outside linkDynamic programming Outside linkDP (CP-Algorithms)
Core: Defining the state and recurrence
Decide what dp[i] means and how it is built from smaller states. With the right state the code is short; with the wrong one, no amount of debugging fixes it.
CodexProblem-solving SimulatorDP: longest common subsequence Outside linkNeetCode DP
Core: One-dimensional DP
Climbing stairs, house robber, coin change and longest increasing subsequence. One array of state, which makes these good problems for learning to read a recurrence off the problem statement.
CodexProblem-solving Outside linkLongest increasing subsequence Outside linkNeetCode 1-D DP
Recommended: Two-dimensional DP
Edit distance, longest common subsequence, grid paths and knapsack. Two indices and a table filled row by row. The simulator shows the order the cells are filled in.
SimulatorDP: longest common subsequence Outside linkEdit distance Outside linkKnapsack problem
Stage 13
Greedy algorithms and divide and conquer
A greedy algorithm takes the best-looking option at each step. For some problems that gives the optimal answer, and for others it fails. Divide and conquer splits a problem, solves the parts and combines them. Both are fast because they avoid exploring every possibility.
Core: Greedy algorithms
Interval scheduling, Huffman coding and coin change with standard coin sets can be solved by always taking the locally best option. The hard part is proving that this gives the overall best answer.
CodexProblem-solving Outside linkGreedy algorithm Outside linkHuffman coding
Core: When greedy fails
The 0/1 knapsack problem and coin change with unusual coin sets break greedy algorithms, and need dynamic programming instead. Recognising these cases matters more than memorising the greedy algorithms.
Outside linkKnapsack problem Outside linkGreedy algorithm CodexProblem-solving
Core: Divide and conquer
Split the problem, solve each part recursively, and combine the results. Merge sort and quicksort work this way, and the master theorem gives their cost.
Outside linkDivide and conquer SimulatorRecursion Outside linkMaster theorem
Recommended: Interval problems
Merge overlapping ranges, find free time slots, or fit the most meetings in a room. Sort by start or end time, then sweep through once. This covers a good number of interview questions.
CodexProblem-solving Outside linkInterval scheduling Outside linkNeetCode intervals
Stage 14
Interview patterns and practice
Once you know the structures and algorithms, the remaining skill is recognising which known technique fits a new problem, quickly, and explaining the trade-offs while you write the code.
Core: Common problem patterns
Two pointers, sliding window, fast and slow pointers, BFS and DFS, top-k with a heap, backtracking and dynamic programming. Around fifteen patterns cover most interview problems, so practising by pattern works better than solving random questions.
CodexProblem-solving SimulatorAlgorithm visualizer Outside linkNeetCode roadmap Outside linkLeetCode patterns
Core: Breaking a problem down
Restate the problem, list the constraints, write the brute-force solution, then improve it. Following these steps keeps you moving when the efficient approach is not obvious, and shows the interviewer how you think.
Core: Communicating while you code
Interviewers grade how you reach the answer as well as the answer. Explain your approach, state the complexity, and test edge cases out loud.
Recommended: Deliberate practice
Revisit problems you got wrong a week later. If you cannot work out the solution again, you remembered the answer rather than the technique.
Recommended: Edge cases and complexity
Empty input, a single element, duplicates, integer overflow and the largest allowed input. State the time and space cost, and the cases that break a simple solution, before you are asked.
After this roadmap
- SimulatorsSorting, heaps, B-trees, Dijkstra, dynamic programming and recursion, animated step by step in the browser.
- Problem solving in the CodexWorked approaches to the problem patterns this roadmap lists.
- CodexLonger study pages on languages, databases, operating systems and distributed systems.