Graphs
graphs
Data Structures
Graphs: Representation Basics
A social network is a graph, a road map is a graph, an `import` graph in your codebase is a graph, and so is the dependency tree of a package manager. The reason graphs feel everywhere is that they are the most general relationship structure: just vertices and edges, with no required root, no acyclic constraint, and no fixed branching factor. **Graphs: Representation Basics** is where you stop drawing them on whiteboards and start storing them in code. This lesson defines the core vocabulary (vertex, edge, degree, path, cycle, directed and undirected, connected and disconnected) and walks through the three canonical representations: an adjacency list backed by a hash map of vertex to neighbors, an adjacency matrix for dense graphs and `O(1)` edge-existence queries, and an edge list for algorithms that just iterate over edges. You will analyze the space and time trade-offs of each so you can pick the right one before writing any traversal logic. In **Hash Map (Dictionary) Basics**, you saw that a hash map maps keys to values in expected `O(1)`; an adjacency list is exactly that, mapping each vertex to its list of neighbors. **Queue & Deque** gave you the FIFO machinery that BFS will run on top of these representations once traversal lessons begin. With a graph stored in memory, the algorithms track is where it comes alive: BFS, DFS, shortest paths, connected components, and the rest of the graph algorithm canon.
Not Started
0%
Union-Find (Disjoint Set Union)
Given a million pairwise 'these two accounts belong to the same person' relations, decide whether two arbitrary accounts are now equivalent. Brute-force flood fills are `O(n)` per query; sorting is the wrong shape entirely. **Union-Find** answers each query in nearly `O(1)` amortized time after the relations are merged, with two primitives and a parent array. This lesson covers the disjoint-set abstraction, the `find` operation that walks parent pointers up to a representative, the `union` operation that links two representatives, and the two optimizations (path compression during `find` and union by rank during `union`) that together push the amortized cost to `O(alpha(n))`, where `alpha` is the inverse Ackermann function (effectively constant for any input you can fit in memory). You will trace the parent array as merges happen, and apply the structure to cycle detection in undirected graphs, connected components, equivalence classes, and Kruskal's minimum spanning tree. In **Arrays & Strings**, you saw that an array can encode a mapping from index to value in `O(1)`; a parent array is exactly that mapping, applied to representative pointers. **Graphs: Representation Basics** gave you the vertex-and-edge vocabulary that Union-Find uses to define connectivity, even though the structure itself stores no edges directly. With Union-Find in your toolkit, the curriculum continues with composite designs that combine multiple primitives, starting with the LRU cache pattern.
Not Started
0%
Weighted Graph Representation
Highways have lengths in kilometers, flights have ticket prices in dollars, and network links have latencies in milliseconds. Treating any of those graphs as unweighted throws away the only information that matters for the question you actually care about (the shortest, cheapest, or fastest route), which is exactly the gap a **Weighted Graph** representation closes by attaching a number to every edge. This lesson covers three representations: a weighted adjacency list backed by arrays of `{node, weight}` pairs, a weighted adjacency matrix where `matrix[u][v]` is the edge cost (and infinity for non-edges), and a weighted edge list that stores `(u, v, weight)` triples. You will analyze the space and time trade-offs, see why Dijkstra wants the adjacency list, why Floyd-Warshall wants the matrix, and why Kruskal wants the edge list, and you will represent both directed and undirected weighted graphs correctly in each format. In **Graphs: Representation Basics**, you stored connectivity (whether an edge exists) using the same three shapes; the weighted version simply replaces a boolean or membership check with a numeric value. **Hash Map (Dictionary) Basics** is what makes the adjacency list work: a vertex maps to its neighbor-and-weight list in expected `O(1)`, the same way the unweighted version did. With weights in the picture, the algorithms track unlocks shortest-path and minimum-spanning-tree algorithms that read the weight on every edge during their core inner loop.
Not Started
0%
Algorithms
Advanced Search Algorithms
Plain BFS finds the shortest path through a 1000x1000 grid by exploring outward in concentric circles, examining about a million cells. A* with a Manhattan-distance heuristic walks almost straight to the target and examines a few thousand. Both algorithms use the same priority-queue framework; the only difference is that A* adds a heuristic estimate to the cost function and biases the search toward the goal. That single addition is what powers GPS, game-pathfinding, and motion planning in robotics. **Advanced Search Algorithms** covers the search refinements that go beyond plain BFS and DFS. You will implement A* with the `f(n) = g(n) + h(n)` cost function, derive what makes a heuristic admissible, and prove the optimality guarantee under admissibility. Bidirectional search runs BFS from both source and target until the frontiers meet, cutting `O(b^d)` to `O(b^(d/2))`. Iterative Deepening DFS combines BFS-style completeness with DFS-style `O(d)` memory, using repeated depth-limited DFS. The lesson finishes with two specialized array searches: Jump search at `O(sqrt(n))` for sorted arrays where binary search is awkward, and interpolation search at `O(log log n)` expected for uniformly distributed keys. In **BFS & DFS (Intro)**, you wrote the basic skeletons. **Graph Algorithms (Core)** introduced Dijkstra's priority-queue relaxation, which A* generalizes by adding the heuristic. Next, **Game Theory** turns to two-player adversarial search.
Not Started
0%
BFS & DFS (Intro)
Swap a queue for a stack inside a graph traversal and you flip from breadth-first to depth-first behavior. The visited-vertex tracking is identical, the neighbor expansion is identical, and yet one explores level by level while the other dives down the longest path first. That single data-structure swap is the entire difference between the two most-used graph algorithms in the field. **BFS & DFS (Intro)** walks through both. For BFS you will implement queue-based level-by-level exploration and use it to find shortest paths in unweighted graphs. For DFS you will see both the recursive form (which uses the call stack implicitly) and the iterative form with an explicit stack, and apply them to connectivity checks, path finding, and cycle detection. The lesson also covers the visited set that prevents infinite loops on cyclic graphs and contrasts graph traversal with tree traversal as a special case. This lesson assumes you are comfortable with three structures from the data-structures track: **Stack (LIFO)** powers iterative DFS, **Queue & Deque** powers BFS, and **Graphs: Representation Basics** gives you the adjacency list or matrix that both algorithms read from. Next, **Hashing Techniques** turns to a different building block, the hash map, which underpins many of the lookup-heavy patterns you will combine with traversal in later lessons.
Not Started
0%
Graph Algorithms (Advanced)
Dijkstra's shortest-path algorithm silently assumes every edge weight is non-negative. Hand it a graph with one negative edge and it can produce a wrong answer with full confidence, because the greedy choice that drives the algorithm no longer reflects the true cost. Real graphs (financial arbitrage detection, currency exchange, time-aware routing) routinely contain negative edges, and that single gap motivates an entire second wave of graph algorithms. **Graph Algorithms (Advanced)** covers that wave. Minimum-spanning-tree algorithms include Kruskal's (sort edges and union components) and Prim's (grow a tree using a priority queue), along with the cut property that explains why both produce the same minimum weight. Shortest paths gain Bellman-Ford for negative edges and negative-cycle detection, plus Floyd-Warshall for all-pairs shortest paths in `O(V^3)`. Strongly connected components are tackled by Kosaraju's (two DFS passes) and Tarjan's (single DFS with low-link values). The lesson also covers articulation points, bridges, Euler paths and circuits via Hierholzer's algorithm, and a first conceptual look at NP-complete Hamiltonian paths. In **Graph Algorithms (Core)**, you implemented Dijkstra, topological sort, and cycle detection. **Union-Find (Disjoint Set Union)** gave you the near-constant-time merge-and-query primitive that makes Kruskal's MST run in `O(E log E)`. From here, **Advanced Graph Algorithms (Network Flow)** turns to capacity-constrained optimization on directed graphs.
Not Started
0%
Graph Algorithms (Core)
Webpack figures out the order to compile your modules using topological sort. Google Maps figures out the route to your destination using Dijkstra. Your CI system rejects circular imports using cycle detection. The same handful of graph algorithms power an enormous slice of real infrastructure, and almost all of them are short additions to a BFS or DFS skeleton you already wrote. **Graph Algorithms (Core)** covers that handful in detail. You will implement topological sort in two ways (Kahn's BFS-with-in-degree algorithm and the DFS-reverse-postorder algorithm), cycle detection on undirected graphs (DFS with parent tracking) and on directed graphs (DFS with white/gray/black coloring), Dijkstra's shortest-path algorithm with a min-heap and the relaxation invariant that makes it work, connected-component counting via DFS or Union-Find, and bipartite checking via two-color BFS. Along the way you will see why Dijkstra fails on negative edge weights, which motivates Bellman-Ford in the advanced lesson later. In **BFS & DFS (Intro)**, you wrote the two traversal skeletons. **Weighted Graph Representation** gave you the adjacency-list-of-tuples format that Dijkstra and friends actually consume. This lesson is where those primitives turn into named algorithms with clear use cases. From here, **Greedy (Intro)** introduces a different paradigm: instead of exploring every option, commit to the locally best choice at each step.
Not Started
0%
Advanced Graph Algorithms (Network Flow)
Two seemingly different problems, the maximum amount of water you can push from a source to a sink through a network of capacitated pipes, and the minimum total capacity you must remove to disconnect the sink from the source, turn out to have the same answer for every graph. The max-flow min-cut theorem ties them together, and once you accept it a surprising number of optimization problems (image segmentation, project selection, bipartite matching) collapse into max-flow instances. **Advanced Graph Algorithms (Network Flow)** introduces the algorithms that compute that maximum flow. You will work through the Ford-Fulkerson method built on augmenting paths and the residual graph, the BFS-based Edmonds-Karp variant with its `O(V * E^2)` guarantee, and Dinic's algorithm which uses level graphs and blocking flows to reach `O(V^2 * E)`. The lesson then turns to maximum bipartite matching (Hungarian and Hopcroft-Karp), applications like airline scheduling and image segmentation, and a first look at minimum-cost flow. In **Graph Algorithms (Advanced)**, you handled MST, all-pairs shortest paths, and SCCs on edge-weighted graphs. Network flow keeps the weighted-edge model but flips the question from "shortest" to "highest throughput." Next, **String Algorithms** turns to pattern matching, the implicit automaton of a regular expression.
Not Started
0%
Practice Problems
Flood Fill
Given a 2D grid representing an image, a starting pixel, and a new color, perform a flood fill (like a paint bucket tool) to recolor the connected region.
Alien Dictionary
Given a sorted list of words in an alien language, determine the order of characters in the alien alphabet using topological sort.
Reconstruct Itinerary
Given a list of airline tickets, reconstruct the itinerary in lexical order starting from 'JFK', using all tickets exactly once.
Swim in Rising Water
Given an n x n grid of elevations, find the minimum time t at which you can swim from the top-left to the bottom-right corner.
Word Ladder
Given a begin word, end word, and a dictionary, find the length of the shortest transformation sequence where each step changes exactly one letter.
Accounts Merge
Given a list of accounts where each account has a name and emails, merge accounts that share a common email address.
Cheapest Flights Within K Stops
Find the cheapest price to fly from a source to a destination with at most k intermediate stops, given a list of flights with prices.
Clone Graph
Given a reference to a node in a connected undirected graph, return a deep copy (clone) of the entire graph.
Number of Connected Components
Given n nodes and a list of undirected edges, find the number of connected components in the graph.
Course Schedule II
Given courses and prerequisites, return a valid order to take all courses (topological ordering), or an empty array if impossible.
Course Schedule
Given a number of courses and their prerequisites, determine if it is possible to finish all courses (detect if the dependency graph has a cycle).
Evaluate Division
Given equations like a/b = k, answer queries asking for the result of x/y using graph traversal on a weighted directed graph.
Graph Valid Tree
Given n nodes and a list of undirected edges, determine if these edges form a valid tree (connected and acyclic).
Max Area of Island
Given a binary grid, find the maximum area of an island (connected group of 1s connected 4-directionally).
Min Cost to Connect All Points
Given an array of points on a 2D plane, find the minimum cost to connect all points such that there is a path between every pair, using Manhattan distance as the edge cost.
Minimum Height Trees
Given a tree of n nodes, find all roots that would minimize the tree's height when the tree is rooted at them.
Network Delay Time
Given a network of n nodes and weighted directed edges representing signal travel times, find the time it takes for a signal sent from node k to reach all nodes.
Number of Islands
Given a 2D grid of '1's (land) and '0's (water), count the number of distinct islands formed by connected land cells.
Number of Provinces
Given an adjacency matrix representing connections between cities, find the total number of provinces (connected components).
Pacific Atlantic Water Flow
Given a matrix of heights, find all cells from which water can flow to both the Pacific and Atlantic oceans.
Redundant Connection
Given a graph that started as a tree with one extra edge added, find and return the edge that can be removed to make it a tree again.
Rotting Oranges
Given a grid where cells contain fresh oranges, rotten oranges, or are empty, determine the minimum time for all fresh oranges to rot via adjacency spreading.
Snakes and Ladders
Given a Snakes and Ladders board, find the minimum number of dice rolls to reach the final square from square 1.
Surrounded Regions
Given a board of 'X' and 'O', capture all regions of 'O' that are completely surrounded by 'X' (not touching the border).
Walls and Gates
Given a grid with walls, gates, and empty rooms, fill each empty room with the distance to its nearest gate using multi-source BFS.
Code Snippets
Graph Adjacency List in Python
An adjacency list represents a graph as 'for each node, the nodes it connects to'. In Python the right shape is `defaultdict(list)`: insertion is one line, traversal is one nested loop, and you do not pay for the V*V matrix. This entry covers building the list, walking it with DFS, and the directed vs undirected detail that bites every newcomer.
Python BFS Template
Breadth-first search visits nodes in order of distance from the start, which makes it the right tool for shortest-path-by-edge-count, level-order traversal, and 'fewest steps' search problems. Python's `collections.deque` gives you O(1) `popleft`, which is the difference between BFS and an O(n^2) accident. This entry covers the standard template, distance tracking, and a level-by-level variant.
Python DFS Templates (Recursive + Iterative)
DFS visits a graph by going as deep as possible before backtracking. Python lets you write it recursively (concise, but bounded by `sys.getrecursionlimit()`) or iteratively with an explicit stack (uglier, but safe for deep graphs). This entry ships both templates and a third variant that detects cycles in a directed graph using gray / black coloring.
Question Banks
Graph Representation Quiz
Short drills on adjacency list vs adjacency matrix, edge-weight storage, and the memory trade-offs between the two formats.
Topological Sort Essentials
Kahn's algorithm, DFS-based ordering, and using topo sort to detect cycles in directed graphs. Code stems are mostly Python.
Graph Theory Essentials
Interview-grade prompts on BFS/DFS, shortest paths, connectivity, and cycle detection across directed and undirected graphs.
Community
Shortest Path in Binary Matrix
BFS through 0-cells in 8 directions to find the shortest path from top-left to bottom-right.
The Union-Find With Rank I Copy Into Every Contest
After timing out on a Codeforces 'connected components' problem twice, I memorized this 25-line union-find with path compression and union-by-rank. The find() is iterative (no recursion to blow the stack) and component_count is O(1).
Find the Town Judge
Identify the unique person trusted by everyone but trusts nobody, using in-degree minus out-degree.
Path with Maximum Probability
Find the path between two nodes that maximizes the product of edge success probabilities, via modified Dijkstra.
Is Graph Bipartite?
Decide whether an undirected graph admits a 2-coloring with no edge sharing a color, using BFS over each component.
Open the Lock
Find the minimum wheel turns to open a 4-digit combination lock while avoiding deadend states.
Find Center of Star Graph
The first two edges of a star graph share exactly one endpoint, and that shared endpoint is the center.
Topological Sort, Three Ways I Have Actually Used It
Build-system DAGs, course-prereq UI ordering, microservice startup choreography. Three production stories from the same Kahn's algorithm boilerplate.
Minimum Genetic Mutation
Transform a gene string to a target one mutation at a time, where each intermediate must be in the bank.
