diff --git a/src/main/java/com/thealgorithms/recursion/TowerOfHanoi.java b/src/main/java/com/thealgorithms/recursion/TowerOfHanoi.java
new file mode 100644
index 000000000000..45471843e998
--- /dev/null
+++ b/src/main/java/com/thealgorithms/recursion/TowerOfHanoi.java
@@ -0,0 +1,64 @@
+package com.thealgorithms.recursion;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * TowerOfHanoi - Solves the classic Tower of Hanoi puzzle
+ *
+ * This algorithm uses recursion to move a stack of disks from a source rod to a
+ * destination rod, following the rules:
+ * 1. Only one disk can be moved at a time.
+ * 2. Each move consists of taking the upper disk from one of the stacks and
+ * placing it on top of another stack.
+ * 3. No disk may be placed on top of a smaller disk.
+ *
+ * Example: If n = 3, Source = 'A', Destination = 'C', Auxiliary = 'B'
+ * Resulting moves will guide disks from A to C using B.
+ *
+ * @author justanothercoder-hub
+ * @see Tower of Hanoi
+ */
+public final class TowerOfHanoi {
+
+ private TowerOfHanoi() {
+ // Utility class
+ }
+
+ /**
+ * Solves the Tower of Hanoi puzzle and returns the list of moves
+ *
+ * @param n number of disks
+ * @param source the source rod
+ * @param destination the destination rod
+ * @param auxiliary the auxiliary rod
+ * @return list of moves as strings
+ */
+ public static List solveTowerOfHanoi(int n, char source, char destination, char auxiliary) {
+ List moves = new ArrayList<>();
+ if (n < 0) {
+ throw new IllegalArgumentException("Number of disks cannot be negative");
+ }
+ moveDisks(n, source, destination, auxiliary, moves);
+ return moves;
+ }
+
+ /**
+ * Recursive helper method to move disks
+ *
+ * @param n number of disks
+ * @param source the source rod
+ * @param destination the destination rod
+ * @param auxiliary the auxiliary rod
+ * @param moves list to record the moves
+ */
+ private static void moveDisks(int n, char source, char destination, char auxiliary, List moves) {
+ if (n == 1) {
+ moves.add("Move disk 1 from rod " + source + " to rod " + destination);
+ return;
+ }
+ moveDisks(n - 1, source, auxiliary, destination, moves);
+ moves.add("Move disk " + n + " from rod " + source + " to rod " + destination);
+ moveDisks(n - 1, auxiliary, destination, source, moves);
+ }
+}
diff --git a/src/test/java/com/thealgorithms/recursion/TowerOfHanoiTest.java b/src/test/java/com/thealgorithms/recursion/TowerOfHanoiTest.java
new file mode 100644
index 000000000000..a82e844ed917
--- /dev/null
+++ b/src/test/java/com/thealgorithms/recursion/TowerOfHanoiTest.java
@@ -0,0 +1,39 @@
+package com.thealgorithms.recursion;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.util.Arrays;
+import java.util.List;
+import org.junit.jupiter.api.Test;
+
+public class TowerOfHanoiTest {
+
+ @Test
+ public void testBaseCase() {
+ List result = TowerOfHanoi.solveTowerOfHanoi(1, 'A', 'C', 'B');
+ assertEquals(1, result.size(), "Should have exactly 1 move for 1 disk");
+ assertEquals("Move disk 1 from rod A to rod C", result.get(0));
+ }
+
+ @Test
+ public void testSmallRecursion() {
+ List result = TowerOfHanoi.solveTowerOfHanoi(2, 'A', 'C', 'B');
+ assertEquals(3, result.size());
+ List expected = Arrays.asList("Move disk 1 from rod A to rod B", "Move disk 2 from rod A to rod C", "Move disk 1 from rod B to rod C");
+ assertEquals(expected, result, "Sequence of moves for 2 disks is incorrect");
+ }
+
+ @Test
+ public void testStandardCase() {
+ List result = TowerOfHanoi.solveTowerOfHanoi(3, 'A', 'C', 'B');
+ assertEquals(7, result.size());
+ assertEquals("Move disk 1 from rod A to rod C", result.get(0));
+ assertEquals("Move disk 1 from rod A to rod C", result.get(6));
+ }
+
+ @Test
+ public void testNegativeInput() {
+ assertThrows(IllegalArgumentException.class, () -> { TowerOfHanoi.solveTowerOfHanoi(-5, 'A', 'C', 'B'); }, "Should throw exception for negative disks");
+ }
+}