Overview
A graph is a set of vertices (nodes) connected by edges. Edges can be directed (one-way, like follows on X) or undirected (two-way, like Facebook friendships), and weighted (distance, cost, time) or unweighted. Trees, grids, linked lists, and state machines are all special graphs.
Before running any graph algorithm, you must choose how to store the graph. An adjacency list (each node maps to its neighbors) is the default for sparse graphs. An adjacency matrix answers 'is there an edge?' in O(1) but uses O(V^2) memory. An edge list is best when you sort edges, as in Kruskal's algorithm.
Intersections are vertices and roads are edges. One-way streets are directed edges, and road lengths are weights. An adjacency list is each intersection's list of directly reachable intersections; an adjacency matrix is a giant table answering 'is there a road from A to B?' for every pair.
When to use it
- Input is given as edges, prerequisites, flights, friendships, or connections.
- Relationships between entities matter more than the entities themselves.
- A grid or word transformation can be modeled as nodes with neighbors.
- You need connectivity, paths, cycles, ordering, or spanning trees.
Problem patterns it solves
Recognize it when: input is edges = [[u, v], ...] or prerequisites.
- 1971. Find if Path Exists in Graph
- 207. Course Schedule
- 997. Find the Town Judge
Recognize it when: neighbors are generated: grid moves, word changes, lock rotations.
- 200. Number of Islands
- 127. Word Ladder
- 752. Open the Lock
Recognize it when: in-degree / out-degree identify sources, sinks, or special nodes.
- 997. Find the Town Judge
- 1557. Minimum Number of Vertices to Reach All Nodes
- 1791. Find Center of Star Graph
Recognize it when: copy nodes and edges; reverse edges.
- 133. Clone Graph
- 802. Find Eventual Safe States
Recognize it when: split into two groups where every edge crosses groups.
- 785. Is Graph Bipartite?
- 886. Possible Bipartition
Where it is used in real software
Users are nodes and follows or friendships are edges; features like people-you-may-know are graph queries.
Google Maps models road segments as weighted directed edges and runs shortest-path algorithms on them.
npm, Maven, and build tools model packages or modules as a directed graph to resolve install and build order.
Graph databases like Neo4j store entities and relationships to detect rings of connected fraudulent accounts.
Key terms
- V, E
- Number of vertices and edges.
- Directed / undirected
- One-way edges vs two-way edges.
- Weighted
- Edges carry a cost such as distance or time.
- Degree
- Number of edges on a node; in-degree and out-degree for directed graphs.
- Sparse / dense
- E close to V vs E close to V^2.
- Connected component
- A maximal group of nodes that are all reachable from each other.
Building an adjacency list
- 1Create an empty list per node
Array of arrays when nodes are 0..n-1; a Map when node ids are strings.
- 2Add each edge
graph[u].push(v). For undirected graphs also graph[v].push(u).
- 3Store weights with neighbors
graph[u].push([v, w]) for weighted graphs.
- 4Track degrees if needed
indegree[v]++ for topological sort or source detection.
Three representations of the same graph
Undirected edges: 0-1, 0-2, 1-2, 2-3
| Representation | Stored data | Edge check | List neighbors | Memory |
|---|---|---|---|---|
| Edge list | [[0,1],[0,2],[1,2],[2,3]] | O(E) | O(E) | O(E) |
| Adjacency list | 0:[1,2] 1:[0,2] 2:[0,1,3] 3:[2] | O(degree) | O(degree) | O(V + E) |
| Adjacency matrix | 4 x 4 grid of 0/1 | O(1) | O(V) | O(V^2) |
NOWRepresentation: Edge list | Stored data: [[0,1],[0,2],[1,2],[2,3]] | Edge check: O(E) | List neighbors: O(E) | Memory: O(E)
Adjacency lists are the default because most real graphs are sparse. Use a matrix for dense graphs or algorithms like Floyd-Warshall that read every pair.
Implementation
// Undirected, nodes 0..n-1function buildGraph(n, edges) { const graph = Array.from({ length: n }, () => []); for (const [u, v] of edges) { graph[u].push(v); graph[v].push(u); } return graph;} // Directed and weighted with string idsfunction buildWeighted(edges) { const graph = new Map(); for (const [from, to, weight] of edges) { if (!graph.has(from)) graph.set(from, []); if (!graph.has(to)) graph.set(to, []); graph.get(from).push([to, weight]); } return graph;} // 997. Find the Town Judge with degreesfunction findJudge(n, trust) { const score = new Array(n + 1).fill(0); // in-degree minus out-degree for (const [a, b] of trust) { score[a]--; score[b]++; } for (let i = 1; i <= n; i++) if (score[i] === n - 1) return i; return -1;} // 785. Is Graph Bipartite? (graph given as adjacency list)function isBipartite(graph) { const color = new Array(graph.length).fill(-1); for (let start = 0; start < graph.length; start++) { if (color[start] !== -1) continue; color[start] = 0; const queue = [start]; for (let head = 0; head < queue.length; head++) { const u = queue[head]; for (const v of graph[u]) { if (color[v] === -1) { color[v] = 1 - color[u]; queue.push(v); } else if (color[v] === color[u]) return false; } } } return true;}Complexity and performance
Best for sparse graphs.
Best for dense graphs.
With an adjacency list.
Must scan whole rows.
Trade-offs
Lists save memory and iterate neighbors quickly; matrices give O(1) edge checks but waste memory on sparse graphs.
For grids and state spaces, generate neighbors on the fly instead of building the whole graph.
Variants and related techniques
Multiple edges between the same pair; keep all of them in the list.
Directed acyclic graph; supports topological order and DP over the order.
Connected, acyclic, with exactly V - 1 edges.
Common mistakes
- Adding only one direction for undirected edges.
Fix: Push both u -> v and v -> u.
- Assuming nodes are 0-indexed.
Fix: Many problems use 1..n; allocate n + 1 or subtract 1.
- Missing isolated nodes.
Fix: Initialize a list for every node, not just nodes that appear in edges.
- Shared inner arrays in JS.
Fix: Use Array.from({ length: n }, () => []) rather than fill([]).
Interview questions
When would you use an adjacency matrix?
When the graph is dense (E close to V^2), when you need constant-time edge checks, or when the algorithm iterates all pairs, such as Floyd-Warshall.
How is a grid a graph?
Each cell is a vertex and each allowed move to a neighboring cell is an edge. You generate neighbors with a directions array instead of storing edges.
Practice problems
| Problem | Difficulty | What it trains |
|---|---|---|
| 1971. Find if Path Exists in Graph | Easy | Build and traverse. |
| 997. Find the Town Judge | Easy | Degrees. |
| 133. Clone Graph | Medium | Copy with a visited map. |
| 785. Is Graph Bipartite? | Medium | Two-coloring. |
| 1557. Minimum Number of Vertices to Reach All Nodes | Medium | In-degree zero. |