🧠
Brute Force (Backtracking with Cycle Detection)
💡 This approach tries all possible orders recursively and checks if they satisfy prerequisites. It is very slow but helps understand the problem deeply and why more efficient methods are needed.
Intuition
Try every possible course order and verify if it respects all prerequisites. If a cycle is detected, backtrack and try another order.
Algorithm
- Generate all permutations of courses.
- For each permutation, check if it satisfies all prerequisite pairs.
- If a permutation satisfies all prerequisites, return it as the valid order.
- If no permutation works, return an empty array.
💡 The brute force method is straightforward but inefficient because it tries every possible order without pruning.
from itertools import permutations
def findOrder(numCourses, prerequisites):
prereq_set = set((a, b) for a, b in prerequisites)
for order in permutations(range(numCourses)):
if all((a, b) not in prereq_set or order.index(b) < order.index(a) for a, b in prerequisites):
return list(order)
return []
# Driver code
if __name__ == '__main__':
print(findOrder(4, [[1,0],[2,0],[3,1],[3,2]]))
Line Notes
from itertools import permutationsImport permutations to generate all possible course orders
prereq_set = set((a, b) for a, b in prerequisites)Convert prerequisites to a set for O(1) lookup
for order in permutations(range(numCourses))Try every possible ordering of courses
if all((a, b) not in prereq_set or order.index(b) < order.index(a) for a, b in prerequisites)Check if current order respects all prerequisites
import java.util.*;
public class Solution {
public List<Integer> findOrder(int numCourses, int[][] prerequisites) {
List<Integer> res = new ArrayList<>();
List<Integer> courses = new ArrayList<>();
for (int i = 0; i < numCourses; i++) courses.add(i);
if (permute(courses, 0, prerequisites, res)) return res;
return new ArrayList<>();
}
private boolean permute(List<Integer> courses, int start, int[][] prerequisites, List<Integer> res) {
if (start == courses.size()) {
if (validOrder(courses, prerequisites)) {
res.addAll(courses);
return true;
}
return false;
}
for (int i = start; i < courses.size(); i++) {
Collections.swap(courses, i, start);
if (permute(courses, start + 1, prerequisites, res)) return true;
Collections.swap(courses, i, start);
}
return false;
}
private boolean validOrder(List<Integer> order, int[][] prerequisites) {
Map<Integer, Integer> pos = new HashMap<>();
for (int i = 0; i < order.size(); i++) pos.put(order.get(i), i);
for (int[] pre : prerequisites) {
if (pos.get(pre[1]) >= pos.get(pre[0])) return false;
}
return true;
}
// Driver
public static void main(String[] args) {
Solution sol = new Solution();
System.out.println(sol.findOrder(4, new int[][]{{1,0},{2,0},{3,1},{3,2}}));
}
}
Line Notes
for (int i = 0; i < numCourses; i++) courses.add(i);Initialize list of courses to permute
if (permute(courses, 0, prerequisites, res)) return res;Start recursive permutation and return if valid order found
Collections.swap(courses, i, start);Swap elements to generate permutations
if (pos.get(pre[1]) >= pos.get(pre[0])) return false;Check if prerequisite order is violated
#include <bits/stdc++.h>
using namespace std;
bool validOrder(const vector<int>& order, const vector<pair<int,int>>& prerequisites) {
unordered_map<int,int> pos;
for (int i = 0; i < (int)order.size(); i++) pos[order[i]] = i;
for (auto& pre : prerequisites) {
if (pos[pre.second] >= pos[pre.first]) return false;
}
return true;
}
bool permute(vector<int>& courses, int start, const vector<pair<int,int>>& prerequisites, vector<int>& res) {
if (start == (int)courses.size()) {
if (validOrder(courses, prerequisites)) {
res = courses;
return true;
}
return false;
}
for (int i = start; i < (int)courses.size(); i++) {
swap(courses[i], courses[start]);
if (permute(courses, start + 1, prerequisites, res)) return true;
swap(courses[i], courses[start]);
}
return false;
}
vector<int> findOrder(int numCourses, vector<pair<int,int>> prerequisites) {
vector<int> courses(numCourses);
iota(courses.begin(), courses.end(), 0);
vector<int> res;
if (permute(courses, 0, prerequisites, res)) return res;
return {};
}
int main() {
vector<pair<int,int>> prereq = {{1,0},{2,0},{3,1},{3,2}};
vector<int> order = findOrder(4, prereq);
for (int c : order) cout << c << ' ';
cout << '\n';
return 0;
}
Line Notes
iota(courses.begin(), courses.end(), 0);Initialize courses vector with 0 to numCourses-1
swap(courses[i], courses[start]);Generate permutations by swapping elements
if (validOrder(courses, prerequisites)) {Check if current permutation respects prerequisites
pos[pre.second] >= pos[pre.first]Detect if prerequisite order is violated
function findOrder(numCourses, prerequisites) {
function* permute(arr, l = 0) {
if (l === arr.length) yield arr.slice();
else {
for (let i = l; i < arr.length; i++) {
[arr[l], arr[i]] = [arr[i], arr[l]];
yield* permute(arr, l + 1);
[arr[l], arr[i]] = [arr[i], arr[l]];
}
}
}
function validOrder(order) {
const pos = new Map();
order.forEach((c, i) => pos.set(c, i));
for (const [a, b] of prerequisites) {
if (pos.get(b) >= pos.get(a)) return false;
}
return true;
}
const courses = Array.from({length: numCourses}, (_, i) => i);
for (const order of permute(courses)) {
if (validOrder(order)) return order;
}
return [];
}
// Driver
console.log(findOrder(4, [[1,0],[2,0],[3,1],[3,2]]));
Line Notes
function* permute(arr, l = 0)Generator function to yield all permutations recursively
[arr[l], arr[i]] = [arr[i], arr[l]];Swap elements to generate permutations
const pos = new Map();Map to store position of each course in current order
if (pos.get(b) >= pos.get(a)) return false;Check if prerequisite order is violated
TimeO(n! * p * n) where n is numCourses and p is number of prerequisites
SpaceO(n) for recursion stack and permutations
We generate all permutations (n!) and for each, check all prerequisites (p) with index lookups (O(n))
💡 For n=4, this means 24 permutations to check, which is manageable, but for n=10, 3.6 million permutations make it infeasible.
Interview Verdict: TLE
This approach is too slow for large inputs but helps understand the problem and why we need efficient algorithms.