diff --git a/src/main/java/com/thealgorithms/datastructures/trees/BinaryTreeToString.java b/src/main/java/com/thealgorithms/datastructures/trees/BinaryTreeToString.java
new file mode 100644
index 000000000000..2f9b3b489d56
--- /dev/null
+++ b/src/main/java/com/thealgorithms/datastructures/trees/BinaryTreeToString.java
@@ -0,0 +1,100 @@
+package com.thealgorithms.datastructures.trees;
+
+/**
+ * Leetcode 606: Construct String from Binary Tree:
+ * https://leetcode.com/problems/construct-string-from-binary-tree/
+ *
+ * Utility class to convert a {@link BinaryTree} into its string representation.
+ *
+ * The conversion follows a preorder traversal pattern (root → left → right)
+ * and uses parentheses to denote the tree structure.
+ * Empty parentheses "()" are used to explicitly represent missing left children
+ * when a right child exists, ensuring the structure is unambiguous.
+ *
+ *
+ * Rules:
+ *
+ * - Each node is represented as {@code (value)}.
+ * - If a node has only a right child, include {@code ()} before the right
+ * child
+ * to indicate the missing left child.
+ * - If a node has no children, it appears as just {@code (value)}.
+ * - The outermost parentheses are removed from the final string.
+ *
+ *
+ * Example:
+ *
+ *
+ * Input tree:
+ * 1
+ * / \
+ * 2 3
+ * \
+ * 4
+ *
+ * Output string:
+ * "1(2()(4))(3)"
+ *
+ *
+ *
+ * This implementation matches the logic from LeetCode problem 606:
+ * Construct String from Binary Tree.
+ *
+ *
+ * @author Muhammad Junaid
+ * @see BinaryTree
+ */
+public class BinaryTreeToString {
+
+ /** String builder used to accumulate the string representation. */
+ private StringBuilder sb;
+
+ /**
+ * Converts a binary tree (given its root node) to its string representation.
+ *
+ * @param root the root node of the binary tree
+ * @return the string representation of the binary tree, or an empty string if
+ * the tree is null
+ */
+ public String tree2str(BinaryTree.Node root) {
+ if (root == null) {
+ return "";
+ }
+
+ sb = new StringBuilder();
+ dfs(root);
+
+ // Remove the leading and trailing parentheses added by the root call
+ return sb.substring(1, sb.length() - 1);
+ }
+
+ /**
+ * Performs a recursive depth-first traversal to build the string.
+ * Each recursive call appends the node value and its children (if any)
+ * enclosed in parentheses.
+ *
+ * @param node the current node being processed
+ */
+ private void dfs(BinaryTree.Node node) {
+ if (node == null) {
+ return;
+ }
+
+ sb.append("(").append(node.data);
+
+ // Recursively build left and right subtrees
+ if (node.left != null) {
+ dfs(node.left);
+ }
+
+ // Handle the special case: right child exists but left child is null
+ if (node.right != null && node.left == null) {
+ sb.append("()");
+ dfs(node.right);
+ } else if (node.right != null) {
+ dfs(node.right);
+ }
+
+ sb.append(")");
+ }
+}
diff --git a/src/main/java/com/thealgorithms/graph/TopologicalSortDFS.java b/src/main/java/com/thealgorithms/graph/TopologicalSortDFS.java
new file mode 100644
index 000000000000..e36d0405683b
--- /dev/null
+++ b/src/main/java/com/thealgorithms/graph/TopologicalSortDFS.java
@@ -0,0 +1,131 @@
+package com.thealgorithms.graph;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Implementation of Topological Sort using Depth-First Search
+ * (DFS).
+ *
+ *
+ * This algorithm returns a valid topological ordering of a directed acyclic
+ * graph (DAG).
+ * If a cycle is detected, meaning the graph cannot be topologically sorted,
+ * it returns an empty array.
+ *
+ *
+ * Use Case: Determining the order of course completion based on
+ * prerequisite dependencies
+ * (commonly known as the “Course Schedule II” problem on LeetCode).
+ * Problem link: LeetCode —
+ * Course Schedule II
+ *
+ *
+ * Algorithm Overview:
+ *
+ * - Each course (node) is visited using DFS.
+ * - During traversal, nodes currently in the recursion stack are tracked to
+ * detect cycles.
+ * - When a node finishes processing, it is added to the output list.
+ * - The output list is then reversed to form a valid topological order.
+ *
+ *
+ *
+ * Time Complexity: O(V + E) — where V is the number of courses
+ * (vertices),
+ * and E is the number of prerequisite relations (edges).
+ *
+ * Space Complexity: O(V + E) — for adjacency list, recursion stack, and
+ * auxiliary sets.
+ *
+ *
+ * Example:
+ *
+ *
+ * int numCourses = 4;
+ * int[][] prerequisites = { { 1, 0 }, { 2, 0 }, { 3, 1 }, { 3, 2 } };
+ * TopologicalSortDFS topo = new TopologicalSortDFS();
+ * int[] order = topo.findOrder(numCourses, prerequisites);
+ * // Possible output: [0, 2, 1, 3]
+ *
+ *
+ * @author Muhammad Junaid
+ */
+public class TopologicalSortDFS {
+
+ /**
+ * Finds a valid topological order of courses given prerequisite constraints.
+ *
+ * @param numCourses the total number of courses labeled from 0 to numCourses
+ * - 1
+ * @param prerequisites an array of prerequisite pairs where each pair [a, b]
+ * indicates that course {@code a} depends on course
+ * {@code b}
+ * @return an integer array representing one possible order to complete all
+ * courses;
+ * returns an empty array if it is impossible (i.e., a cycle exists)
+ */
+ public int[] findOrder(int numCourses, int[][] prerequisites) {
+ Map> prereq = new HashMap<>();
+ for (int i = 0; i < numCourses; i++) {
+ prereq.put(i, new ArrayList<>());
+ }
+ for (int[] pair : prerequisites) {
+ int crs = pair[0];
+ int pre = pair[1];
+ prereq.get(crs).add(pre);
+ }
+
+ List output = new ArrayList<>();
+ Set visited = new HashSet<>();
+ Set cycle = new HashSet<>();
+
+ for (int c = 0; c < numCourses; c++) {
+ if (!dfs(c, prereq, visited, cycle, output)) {
+ return new int[0]; // Cycle detected — impossible order
+ }
+ }
+
+ return output.stream().mapToInt(Integer::intValue).toArray();
+ }
+
+ /**
+ * Performs a depth-first search to visit all prerequisites of a course.
+ *
+ * @param crs the current course being visited
+ * @param prereq adjacency list mapping courses to their prerequisites
+ * @param visited set of courses that have been completely processed
+ * @param cycle set of courses currently in the recursion stack (used for
+ * cycle detection)
+ * @param output list that accumulates the topological order in reverse
+ * @return {@code true} if the current course and its prerequisites can be
+ * processed without cycles;
+ * {@code false} if a cycle is detected
+ */
+ private boolean dfs(int crs, Map> prereq, Set visited, Set cycle, List output) {
+
+ if (cycle.contains(crs)) {
+ return false; // Cycle detected
+ }
+ if (visited.contains(crs)) {
+ return true; // Already processed
+ }
+
+ cycle.add(crs);
+ for (int pre : prereq.get(crs)) {
+ if (!dfs(pre, prereq, visited, cycle, output)) {
+ return false;
+ }
+ }
+
+ cycle.remove(crs);
+ visited.add(crs);
+ output.add(crs);
+ return true;
+ }
+}
diff --git a/src/test/java/com/thealgorithms/datastructures/trees/BinaryTreeToStringTest.java b/src/test/java/com/thealgorithms/datastructures/trees/BinaryTreeToStringTest.java
new file mode 100644
index 000000000000..2461fd74143d
--- /dev/null
+++ b/src/test/java/com/thealgorithms/datastructures/trees/BinaryTreeToStringTest.java
@@ -0,0 +1,57 @@
+package com.thealgorithms.datastructures.trees;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests for the BinaryTreeToString class.
+ */
+public class BinaryTreeToStringTest {
+
+ @Test
+ public void testTreeToStringBasic() {
+ BinaryTree tree = new BinaryTree();
+ tree.put(1);
+ tree.put(2);
+ tree.put(3);
+ tree.put(4);
+
+ BinaryTreeToString converter = new BinaryTreeToString();
+ String result = converter.tree2str(tree.getRoot());
+
+ // Output will depend on insertion logic of BinaryTree.put()
+ // which is BST-style, so result = "1()(2()(3()(4)))"
+ Assertions.assertEquals("1()(2()(3()(4)))", result);
+ }
+
+ @Test
+ public void testSingleNodeTree() {
+ BinaryTree tree = new BinaryTree();
+ tree.put(10);
+
+ BinaryTreeToString converter = new BinaryTreeToString();
+ String result = converter.tree2str(tree.getRoot());
+
+ Assertions.assertEquals("10", result);
+ }
+
+ @Test
+ public void testComplexTreeStructure() {
+ BinaryTree.Node root = new BinaryTree.Node(10);
+ root.left = new BinaryTree.Node(5);
+ root.right = new BinaryTree.Node(20);
+ root.right.left = new BinaryTree.Node(15);
+ root.right.right = new BinaryTree.Node(25);
+
+ BinaryTreeToString converter = new BinaryTreeToString();
+ String result = converter.tree2str(root);
+
+ Assertions.assertEquals("10(5)(20(15)(25))", result);
+ }
+
+ @Test
+ public void testNullTree() {
+ BinaryTreeToString converter = new BinaryTreeToString();
+ Assertions.assertEquals("", converter.tree2str(null));
+ }
+}
diff --git a/src/test/java/com/thealgorithms/graph/TopologicalSortDFSTest.java b/src/test/java/com/thealgorithms/graph/TopologicalSortDFSTest.java
new file mode 100644
index 000000000000..7e169003ba12
--- /dev/null
+++ b/src/test/java/com/thealgorithms/graph/TopologicalSortDFSTest.java
@@ -0,0 +1,76 @@
+package com.thealgorithms.graph;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+public class TopologicalSortDFSTest {
+ private TopologicalSortDFS topologicalSortDFS;
+
+ @BeforeEach
+ public void setUp() {
+ topologicalSortDFS = new TopologicalSortDFS();
+ }
+
+ @Test
+ public void testSimpleCase() {
+ // Example: Two courses where 1 depends on 0
+ int numCourses = 2;
+ int[][] prerequisites = {{1, 0}};
+ int[] expected = {0, 1};
+
+ int[] result = topologicalSortDFS.findOrder(numCourses, prerequisites);
+
+ assertArrayEquals(expected, result, "Expected order is [0, 1].");
+ }
+
+ @Test
+ public void testMultipleDependencies() {
+ // Example: 4 courses with dependencies
+ // 1 -> 0, 2 -> 0, 3 -> 1, 3 -> 2
+ int numCourses = 4;
+ int[][] prerequisites = {{1, 0}, {2, 0}, {3, 1}, {3, 2}};
+ int[] result = topologicalSortDFS.findOrder(numCourses, prerequisites);
+
+ // Valid answers could be [0,1,2,3] or [0,2,1,3]
+ int[] expected = {0, 1, 2, 3};
+ assertArrayEquals(expected, result, "Valid topological order expected, e.g., [0,1,2,3] or [0,2,1,3].");
+ }
+
+ @Test
+ public void testNoDependencies() {
+ // Example: 3 courses with no dependencies
+ int numCourses = 3;
+ int[][] prerequisites = {};
+ int[] expected = {0, 1, 2};
+
+ int[] result = topologicalSortDFS.findOrder(numCourses, prerequisites);
+
+ assertArrayEquals(expected, result, "Any order is valid when there are no dependencies.");
+ }
+
+ @Test
+ public void testCycleGraph() {
+ // Example: A cycle exists (0 -> 1 -> 0)
+ int numCourses = 2;
+ int[][] prerequisites = {{0, 1}, {1, 0}};
+ int[] expected = {};
+
+ int[] result = topologicalSortDFS.findOrder(numCourses, prerequisites);
+
+ assertArrayEquals(expected, result, "Cycle detected, no valid course order.");
+ }
+
+ @Test
+ public void testComplexGraph() {
+ // Complex example: 6 courses
+ // Dependencies: 5->2, 5->0, 4->0, 4->1, 2->3, 3->1
+ int numCourses = 6;
+ int[][] prerequisites = {{2, 5}, {0, 5}, {0, 4}, {1, 4}, {3, 2}, {1, 3}};
+ int[] result = topologicalSortDFS.findOrder(numCourses, prerequisites);
+ // Valid order: [5, 4, 2, 3, 1, 0]
+ int[] expected = {5, 4, 0, 2, 3, 1};
+ assertArrayEquals(expected, result, "Valid topological order expected such as [5, 4, 0, 2, 3, 1].");
+ }
+}