From 8b89e9debf04aca5ec0fd068df00f81c1c198c8d Mon Sep 17 00:00:00 2001 From: shreeya-g10 Date: Wed, 19 Nov 2025 03:22:01 +0530 Subject: [PATCH 1/3] Add unique permutation algorithm and test cases --- .../backtracking/UniquePermutation.java | 60 +++++++++++++++++++ .../backtracking/UniquePermutationTest.java | 31 ++++++++++ 2 files changed, 91 insertions(+) create mode 100644 src/main/java/com/thealgorithms/backtracking/UniquePermutation.java create mode 100644 src/test/java/com/thealgorithms/backtracking/UniquePermutationTest.java diff --git a/src/main/java/com/thealgorithms/backtracking/UniquePermutation.java b/src/main/java/com/thealgorithms/backtracking/UniquePermutation.java new file mode 100644 index 000000000000..649d2a9bfc1b --- /dev/null +++ b/src/main/java/com/thealgorithms/backtracking/UniquePermutation.java @@ -0,0 +1,60 @@ +package com.thealgorithms.backtracking; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Generates all UNIQUE permutations of a string, even when duplicate characters exist. + * + * Example: + * Input: "AAB" + * Output: ["AAB", "ABA", "BAA"] + * + * Time Complexity: O(n! * n) + */ +public final class UniquePermutation { + + private UniquePermutation() { + // Prevent instantiation + throw new UnsupportedOperationException("Utility class"); + } + + public static List generateUniquePermutations(String input) { + List result = new ArrayList<>(); + if (input == null) return result; + + char[] chars = input.toCharArray(); + Arrays.sort(chars); // important: sort to detect duplicates + + backtrack(chars, new boolean[chars.length], new StringBuilder(), result); + return result; + } + + private static void backtrack(char[] chars, boolean[] used, StringBuilder current, List result) { + + if (current.length() == chars.length) { + result.add(current.toString()); + return; + } + + for (int i = 0; i < chars.length; i++) { + + // skip duplicates + if (i > 0 && chars[i] == chars[i - 1] && !used[i - 1]) { + continue; + } + + if (!used[i]) { + used[i] = true; + current.append(chars[i]); + + backtrack(chars, used, current, result); + + // undo changes + used[i] = false; + current.deleteCharAt(current.length() - 1); + } + } + } +} diff --git a/src/test/java/com/thealgorithms/backtracking/UniquePermutationTest.java b/src/test/java/com/thealgorithms/backtracking/UniquePermutationTest.java new file mode 100644 index 000000000000..cc2941d0c2e6 --- /dev/null +++ b/src/test/java/com/thealgorithms/backtracking/UniquePermutationTest.java @@ -0,0 +1,31 @@ +package com.thealgorithms.backtracking; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.Arrays; +import java.util.List; +import org.junit.jupiter.api.Test; + +public class UniquePermutationTest { + + @Test + void testUniquePermutations_AAB() { + List expected = Arrays.asList("AAB", "ABA", "BAA"); + List result = UniquePermutation.generateUniquePermutations("AAB"); + assertEquals(expected, result); + } + + @Test + void testUniquePermutations_ABC() { + List expected = Arrays.asList("ABC", "ACB", "BAC", "BCA", "CAB", "CBA"); + List result = UniquePermutation.generateUniquePermutations("ABC"); + assertEquals(expected, result); + } + + @Test + void testEmptyString() { + List expected = Arrays.asList(""); + List result = UniquePermutation.generateUniquePermutations(""); + assertEquals(expected, result); + } +} From af2a51d978e1b909987cae63fe45ca424c56e4e5 Mon Sep 17 00:00:00 2001 From: shreeya-g10 Date: Wed, 19 Nov 2025 03:38:44 +0530 Subject: [PATCH 2/3] Fix: add braces for checkstyle --- .../com/thealgorithms/backtracking/UniquePermutation.java | 4 +++- .../thealgorithms/backtracking/UniquePermutationTest.java | 8 ++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/thealgorithms/backtracking/UniquePermutation.java b/src/main/java/com/thealgorithms/backtracking/UniquePermutation.java index 649d2a9bfc1b..4804e247ab03 100644 --- a/src/main/java/com/thealgorithms/backtracking/UniquePermutation.java +++ b/src/main/java/com/thealgorithms/backtracking/UniquePermutation.java @@ -22,7 +22,9 @@ private UniquePermutation() { public static List generateUniquePermutations(String input) { List result = new ArrayList<>(); - if (input == null) return result; + if (input == null) { + return result; + } char[] chars = input.toCharArray(); Arrays.sort(chars); // important: sort to detect duplicates diff --git a/src/test/java/com/thealgorithms/backtracking/UniquePermutationTest.java b/src/test/java/com/thealgorithms/backtracking/UniquePermutationTest.java index cc2941d0c2e6..97c07350168a 100644 --- a/src/test/java/com/thealgorithms/backtracking/UniquePermutationTest.java +++ b/src/test/java/com/thealgorithms/backtracking/UniquePermutationTest.java @@ -1,22 +1,22 @@ package com.thealgorithms.backtracking; -import static org.junit.jupiter.api.Assertions.assertEquals; - import java.util.Arrays; import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; public class UniquePermutationTest { @Test - void testUniquePermutations_AAB() { + void testUniquePermutationsAab() { List expected = Arrays.asList("AAB", "ABA", "BAA"); List result = UniquePermutation.generateUniquePermutations("AAB"); assertEquals(expected, result); } @Test - void testUniquePermutations_ABC() { + void testUniquePermutationsAbc() { List expected = Arrays.asList("ABC", "ACB", "BAC", "BCA", "CAB", "CBA"); List result = UniquePermutation.generateUniquePermutations("ABC"); assertEquals(expected, result); From 016a76f6c49d8df3bf89375abe1a464ff4921ff2 Mon Sep 17 00:00:00 2001 From: shreeya-g10 Date: Wed, 19 Nov 2025 03:44:26 +0530 Subject: [PATCH 3/3] Apply clang-format --- .../com/thealgorithms/backtracking/UniquePermutationTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/thealgorithms/backtracking/UniquePermutationTest.java b/src/test/java/com/thealgorithms/backtracking/UniquePermutationTest.java index 97c07350168a..c8e7cd0af0dd 100644 --- a/src/test/java/com/thealgorithms/backtracking/UniquePermutationTest.java +++ b/src/test/java/com/thealgorithms/backtracking/UniquePermutationTest.java @@ -1,9 +1,9 @@ package com.thealgorithms.backtracking; +import static org.junit.jupiter.api.Assertions.assertEquals; + import java.util.Arrays; import java.util.List; - -import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; public class UniquePermutationTest {