Skip to content

Added Topological sorting algorithm using BFS and DFS #5710

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package com.thealgorithms.datastructures.graphs;

import java.util.*;

/**
* This class provides an implementation of Topological Sort using BFS (Kahn's
* Algorithm)
* for the Course Schedule problem (LeetCode 207).
*
* @author Lochan Paudel
*/
public class TopologicalSortBFS {

/**
* This method performs topological sort using BFS to determine if all courses
* can be completed.
*
* @param numCourses Total number of courses
* @param prerequisites A 2D array where prerequisites[i] = [a, b] indicates
* that course b must be taken before course a
* @return true if all courses can be finished, false otherwise
*/
public boolean canFinish(int numCourses, int[][] prerequisites) {
// Edge Case: No courses or no prerequisites
if (numCourses == 0 || prerequisites == null) {
return true;
}

// Initialize graph and in-degree array
List<List<Integer>> graph = new ArrayList<>();
int[] inDegree = new int[numCourses];

// Build the graph (adjacency list) and fill in-degree array
for (int i = 0; i < numCourses; i++) {
graph.add(new ArrayList<>());
}

for (int[] pre : prerequisites) {
int course = pre[0];
int prerequisite = pre[1];
graph.get(prerequisite).add(course);
inDegree[course]++;
}

// Initialize queue for BFS
Queue<Integer> queue = new LinkedList<>();

// Add courses with no prerequisites (in-degree 0) to the queue
for (int i = 0; i < numCourses; i++) {
if (inDegree[i] == 0) {
queue.add(i);
}
}

// Number of courses processed
int processedCourses = 0;

// Process courses in BFS order
while (!queue.isEmpty()) {
int course = queue.poll();
processedCourses++;

for (int neighbor : graph.get(course)) {
inDegree[neighbor]--;
if (inDegree[neighbor] == 0) {
queue.add(neighbor);
}
}
}

// If we've processed all courses, return true, otherwise return false (cycle
// detected)
return processedCourses == numCourses;
}

/**
* Main method for testing the Topological Sort BFS solution.
*/
public static void main(String[] args) {
TopologicalSortBFS ts = new TopologicalSortBFS();

// Test cases
System.out.println(ts.canFinish(2, new int[][] { { 1, 0 } })); // true
System.out.println(ts.canFinish(2, new int[][] { { 1, 0 }, { 0, 1 } })); // false
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package com.thealgorithms.datastructures.graphs;

import java.util.*;

/**
* This class provides an implementation of Topological Sort using DFS
* for the Course Schedule problem (LeetCode 207).
*
* @author Lochan Paudel
*/
public class TopologicalSortDFS {

/**
* This method performs topological sort using DFS to determine if all courses
* can be completed.
*
* @param numCourses Total number of courses
* @param prerequisites A 2D array where prerequisites[i] = [a, b] indicates
* that course b must be taken before course a
* @return true if all courses can be finished, false otherwise
*/
public boolean canFinish(int numCourses, int[][] prerequisites) {
// Edge Case: No courses or no prerequisites
if (numCourses == 0 || prerequisites == null) {
return true;
}

// Initialize graph
List<List<Integer>> graph = new ArrayList<>();
for (int i = 0; i < numCourses; i++) {
graph.add(new ArrayList<>());
}

// Build the graph (adjacency list)
for (int[] pre : prerequisites) {
int course = pre[0];
int prerequisite = pre[1];
graph.get(prerequisite).add(course);
}

// Array to track visiting and visited nodes
int[] visited = new int[numCourses];

// Perform DFS for all courses
for (int i = 0; i < numCourses; i++) {
if (!dfs(i, graph, visited)) {
return false; // If a cycle is found, return false
}
}

return true; // No cycle found, return true
}

/**
* Helper method to perform DFS and detect cycles.
*
* @param course The current course
* @param graph The adjacency list of the graph
* @param visited Array to keep track of visit status (0 = unvisited, 1 =
* visiting, 2 = visited)
* @return true if no cycle is detected, otherwise false
*/
private boolean dfs(int course, List<List<Integer>> graph, int[] visited) {
if (visited[course] == 1) {
return false; // Cycle detected (back edge)
}
if (visited[course] == 2) {
return true; // Already visited, no cycle here
}

visited[course] = 1; // Mark course as visiting

for (int neighbor : graph.get(course)) {
if (!dfs(neighbor, graph, visited)) {
return false;
}
}

visited[course] = 2; // Mark course as fully visited
return true;
}

/**
* Main method for testing the Topological Sort DFS solution.
*/
public static void main(String[] args) {
TopologicalSortDFS ts = new TopologicalSortDFS();

// Test cases
System.out.println(ts.canFinish(2, new int[][] { { 1, 0 } })); // true
System.out.println(ts.canFinish(2, new int[][] { { 1, 0 }, { 0, 1 } })); // false
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package com.thealgorithms.datastructures.lists;

/**
* This class provides an implementation of cycle detection in a linked list
* using Floyd's Cycle Detection Algorithm (Tortoise and Hare Algorithm).
*
* The algorithm uses two pointers: slow and fast. The slow pointer moves
* one step at a time, while the fast pointer moves two steps. If there is a
* cycle in the linked list, the two pointers will meet; otherwise, the fast
* pointer will reach the end of the list.
*
* @author Lochan Paudel
*/
class ListNode {
int val;
ListNode next;

ListNode(int val) {
this.val = val;
this.next = null;
}
}

public class LinkedListCycleDetection {

/**
* Function to detect a cycle in the linked list using Floyd's Cycle Detection
* Algorithm.
*
* @param head The head of the linked list
* @return true if a cycle is detected, otherwise false
*/
public static boolean hasCycle(ListNode head) {
if (head == null || head.next == null) {
return false; // Edge Case 1: List is empty or contains only one node (no cycle possible)
}

ListNode slow = head;
ListNode fast = head;

// Traverse the list with two pointers
while (fast != null && fast.next != null) {
slow = slow.next; // Move slow pointer by one step
fast = fast.next.next; // Move fast pointer by two steps

if (slow == fast) { // If the pointers meet, a cycle is detected
return true;
}
}

return false; // No cycle detected
}

/**
* Main method to run test cases
*
* Test cases include:
* 1. Empty list
* 2. Single node with no cycle
* 3. Multiple nodes with no cycle
* 4. Multiple nodes with a cycle
*/
public static void main(String[] args) {
// Test Case 1: Empty List (Edge Case)
ListNode head1 = null;
System.out.println("Test Case 1 (Empty List): " + (hasCycle(head1) ? "Cycle Detected" : "No Cycle"));

// Test Case 2: Single node, no cycle (Edge Case)
ListNode head2 = new ListNode(1);
System.out.println("Test Case 2 (Single Node, No Cycle): " + (hasCycle(head2) ? "Cycle Detected" : "No Cycle"));

// Test Case 3: Multiple nodes, no cycle
ListNode head3 = new ListNode(1);
head3.next = new ListNode(2);
head3.next.next = new ListNode(3);
System.out.println(
"Test Case 3 (Multiple Nodes, No Cycle): " + (hasCycle(head3) ? "Cycle Detected" : "No Cycle"));

// Test Case 4: Multiple nodes, with cycle
ListNode head4 = new ListNode(1);
ListNode second = new ListNode(2);
ListNode third = new ListNode(3);
ListNode fourth = new ListNode(4);
head4.next = second;
second.next = third;
third.next = fourth;
fourth.next = second; // Creates a cycle
System.out.println("Test Case 4 (Multiple Nodes, Cycle): " + (hasCycle(head4) ? "Cycle Detected" : "No Cycle"));
}
}
Loading