Given a Directed Acyclic Graph (DAG) of V (0 to V-1) vertices and E edges represented as a 2D list of edges[][], where each entry edges[i] = [u, v] denotes an directededge u -> v. Return topological sort for the given graph.
Topological sorting for Directed Acyclic Graph (DAG) is a linear ordering of vertices such that for every directed edge u -> v, vertex u comes before v in the ordering.
Note: As there are multiple Topological orders possible, you may return any of them. If your returned Topological sort is correct then the output will be true else false.
Examples:
Input: V = 4, E = 3, edges[][] = [[3, 0], [1, 0], [2, 0]]
Output: true
Explanation: The output true denotes that the order is valid. Few valid Topological orders for the given graph are: [3, 2, 1, 0]
[1, 2, 3, 0]
[2, 3, 1, 0]
Input: V = 6, E = 6, edges[][] = [[1, 3], [2, 3], [4, 1], [4, 0], [5, 0], [5,2]]
Output: true Explanation: The output true denotes that the order is valid. Few valid Topological orders for the graph are:
[4, 5, 0, 1, 2, 3]
[5, 2, 4, 0, 1, 3]
Constraints:
2 ≤ V ≤ 103
1 ≤ E = edges.size() ≤ (V * (V – 1)) / 2
Approach 01:
-
C++
-
Python
#include <vector>
#include <queue>
using namespace std;
class Solution {
public:
vector<int> topoSort(int vertexCount, vector<vector<int>>& edges) {
vector<int> inDegree(vertexCount, 0);
vector<int> adjacencyList[vertexCount];
vector<int> topologicalOrder;
// Build the graph and compute in-degrees
for (int i = 0; i < edges.size(); i++) {
int fromNode = edges[i][0];
int toNode = edges[i][1];
inDegree[toNode]++;
adjacencyList[fromNode].push_back(toNode);
}
queue<int> bfsQueue;
for (int node = 0; node < vertexCount; node++) {
if (inDegree[node] == 0) {
bfsQueue.push(node);
}
}
// Kahn's algorithm (BFS-based topological sort)
while (!bfsQueue.empty()) {
int currentNode = bfsQueue.front();
bfsQueue.pop();
topologicalOrder.push_back(currentNode);
for (int neighbor : adjacencyList[currentNode]) {
inDegree[neighbor]--;
if (inDegree[neighbor] == 0) {
bfsQueue.push(neighbor);
}
}
}
// Optional: if graph contains a cycle, remaining nodes will still have in-degree > 0
for (int node = 0; node < vertexCount; node++) {
if (inDegree[node] > 0) {
topologicalOrder.push_back(node);
}
}
return topologicalOrder;
}
};
from collections import deque
from typing import List
class Solution:
def topoSort(self, vertexCount: int, edges: List[List[int]]) -> List[int]:
inDegree = [0] * vertexCount
adjacencyList = [[] for _ in range(vertexCount)]
topologicalOrder = []
# Build the graph and compute in-degrees
for fromNode, toNode in edges:
inDegree[toNode] += 1
adjacencyList[fromNode].append(toNode)
bfsQueue = deque()
for node in range(vertexCount):
if inDegree[node] == 0:
bfsQueue.append(node)
# Kahn's algorithm (BFS-based topological sort)
while bfsQueue:
currentNode = bfsQueue.popleft()
topologicalOrder.append(currentNode)
for neighbor in adjacencyList[currentNode]:
inDegree[neighbor] -= 1
if inDegree[neighbor] == 0:
bfsQueue.append(neighbor)
# Optional: if graph contains a cycle, include remaining nodes
for node in range(vertexCount):
if inDegree[node] > 0:
topologicalOrder.append(node)
return topologicalOrder
Time Complexity:
- Building the Graph:
Each edge is processed once to populate the adjacency list and compute in-degrees, which takes \( O(E) \) time.
- Queue Initialization:
All vertices are checked for zero in-degree, which takes \( O(V) \) time.
- BFS Traversal:
Each vertex is added to the queue at most once and each edge is traversed once, contributing \( O(V + E) \) time.
- Cycle Check:
All vertices are scanned again to check for remaining in-degrees, which takes \( O(V) \) time.
- Total Time Complexity:
\( O(V + E) \)
Space Complexity:
- Adjacency List:
Stores all edges once, taking \( O(V + E) \) space.
- In-degree Array and Output Vector:
Both use \( O(V) \) space.
- Queue:
In the worst case, the queue holds all vertices, which is \( O(V) \) space.
- Total Space Complexity:
\( O(V + E) \)

