How to reverse a graph in linear time?
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.
Introduction
Reversing a directed graph means creating a new graph in which every edge u -> v becomes v -> u. If the graph is stored as adjacency lists, this can be done in linear time, O(V + E), because you visit each vertex once and each edge once.
Why the Linear-Time Bound Is Possible
For adjacency-list graphs, the input already organizes outgoing edges by source vertex. Reversal only requires scanning those lists and appending reversed edges into a new adjacency list structure.
You do not need any expensive search or sorting step. The work is proportional to the size of the graph representation itself.
Python Example with Adjacency Lists
Suppose the graph is a dictionary mapping each node to a list of outgoing neighbors.
Output:
Every original edge is processed exactly once.
Watch the Vertex Set Carefully
The code above assumes every vertex already appears as a key in the dictionary, even if it has no outgoing edges. That is important because the reversed graph still needs entries for sink nodes and isolated nodes.
If your input representation omits vertices with empty adjacency lists, add them first or discover them while scanning edges.
Example in C++
The same idea works naturally with vectors.
This is still O(V + E) because the nested loop touches each stored edge once.
Why This Matters in Real Algorithms
Graph reversal is not just a toy transformation. It appears in algorithms such as:
- Kosaraju’s strongly connected components algorithm
- reverse reachability analysis
- computing predecessor relationships in control-flow graphs
- solving dependency questions from the opposite direction
So the linear-time transpose operation is often a core building block.
Adjacency Matrix Case
If the graph is stored as an adjacency matrix, reversal is just matrix transpose. But that representation has different complexity characteristics because the matrix already uses O(V^2) space. In that case, “linear time” relative to the matrix representation means something different from adjacency-list linear time.
For sparse graphs, adjacency lists are usually the better fit.
Common Pitfalls
A common mistake is forgetting to create empty adjacency lists for vertices that have no incoming edges in the reversed graph. Another is writing an algorithm that repeatedly searches for incoming edges, which degrades performance toward O(V * E) or worse. Developers also sometimes mix up graph reversal with undirected-edge duplication, but reversal matters only for directed graphs because edge direction actually changes.
Summary
- Reverse a directed graph by scanning every edge and flipping its direction.
- With adjacency lists, the operation is
O(V + E). - Initialize the reversed graph with all vertices, including those with no neighbors.
- The technique is a standard building block in SCC and reverse-reachability algorithms.
- Avoid repeated searches for incoming edges; one pass over the edge set is enough.
Related reading
- How to reverse a number as an integer and not as a string?
- How to reverse a singly linked list using only two pointers?
- How to reverse a string in O1 complexity runtime?
- How to rewrite a nested loop using the C STL algorithms?
- How to rotate a matrix 90 degrees without using any extra space?
- How to run function on the deepest level only in a nested list?
- How to run TensorFlow on multiple nodes with several CPUs each
- how to save shortest path in dijkstra algorithm

DSA Fundamentals
Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.