Skip to content

Commit 9c55ec0

Browse files
author
alxkm
committed
refactor: PermuteString
1 parent 74b05ef commit 9c55ec0

File tree

2 files changed

+91
-35
lines changed

2 files changed

+91
-35
lines changed

src/main/java/com/thealgorithms/strings/PermuteString.java

+54-35
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,69 @@
11
package com.thealgorithms.strings;
22

3-
/*
4-
Backtracking algorithm used in the program:-
3+
import java.util.Set;
54

6-
>>Fix a character in the first position and swap the rest of the character with the first character.
7-
Like in ABC, in the first iteration three strings are formed: ABC, BAC, and CBA by swapping A with
8-
A, B and C respectively.
9-
>>Repeat step 1 for the rest of the characters like fixing second character B and so on.
10-
>>Now swap again to go back to the previous position. E.g., from ABC, we formed ABC by fixing B
11-
again, and we backtrack to the previous position and swap B with C. So, now we got ABC and ACB.
12-
>>Repeat these steps for BAC and CBA, to get all the permutations.
5+
/**
6+
* This class provides methods for generating all permutations of a given string using a backtracking algorithm.
7+
* <p>
8+
* The algorithm works as follows:
9+
* <ol>
10+
* <li>Fix a character in the current position and swap it with each of the remaining characters.
11+
* For example, for the string "ABC":
12+
* <ul>
13+
* <li>Fix 'A' at the first position: permutations are "ABC", "BAC", "CBA" (obtained by swapping 'A' with 'B' and 'C' respectively).</li>
14+
* </ul>
15+
* </li>
16+
* <li>Repeat the process for the next character.
17+
* For instance, after fixing 'B' in the second position:
18+
* <ul>
19+
* <li>For "BAC", the permutations include "BAC" and "BCA" (after swapping 'A' and 'C').</li>
20+
* </ul>
21+
* </li>
22+
* <li>After generating permutations for the current position, backtrack by swapping the characters back to their original positions to restore the state.
23+
* For example, after generating permutations for "ABC", swap back to restore "BAC" and continue with further permutations.</li>
24+
* <li>Repeat the process for all characters to get all possible permutations.</li>
25+
* </ol>
26+
* </p>
1327
*/
1428
public final class PermuteString {
1529
private PermuteString() {
1630
}
1731

18-
// Function for swapping the characters at position I with character at position j
19-
public static String swapString(String a, int i, int j) {
20-
char[] b = a.toCharArray();
21-
char ch;
22-
ch = b[i];
23-
b[i] = b[j];
24-
b[j] = ch;
25-
return String.valueOf(b);
32+
/**
33+
* Swaps the characters at the specified positions in the given string.
34+
*
35+
* @param str the string in which characters will be swapped
36+
* @param i the position of the first character to swap
37+
* @param j the position of the second character to swap
38+
* @return a new string with the characters at positions i and j swapped
39+
*/
40+
public static String swapCharacters(String str, int i, int j) {
41+
char[] chars = str.toCharArray();
42+
char temp = chars [i];
43+
chars [i] = chars [j];
44+
chars [j] = temp;
45+
return new String(chars);
2646
}
2747

28-
public static void main(String[] args) {
29-
String str = "ABC";
30-
int len = str.length();
31-
System.out.println("All the permutations of the string are: ");
32-
generatePermutation(str, 0, len);
33-
}
34-
35-
// Function for generating different permutations of the string
36-
public static void generatePermutation(String str, int start, int end) {
37-
// Prints the permutations
48+
/**
49+
* Generates all permutations of the given string and collects them into a set.
50+
*
51+
* @param str the string to permute
52+
* @param start the starting index for the current permutation
53+
* @param end the end index (length of the string)
54+
* @param permutations the set to collect all unique permutations
55+
*/
56+
public static void generatePermutations(String str, int start, int end, Set<String> permutations) {
3857
if (start == end - 1) {
39-
System.out.println(str);
58+
permutations.add(str);
4059
} else {
41-
for (int i = start; i < end; i++) {
42-
// Swapping the string by fixing a character
43-
str = swapString(str, start, i);
44-
// Recursively calling function generatePermutation() for rest of the characters
45-
generatePermutation(str, start + 1, end);
46-
// Backtracking and swapping the characters again.
47-
str = swapString(str, start, i);
60+
for (int currentIndex = start; currentIndex < end; currentIndex++) {
61+
// Swap the current character with the character at the start index
62+
str = swapCharacters(str, start, currentIndex);
63+
// Recursively generate permutations for the remaining characters
64+
generatePermutations(str, start + 1, end, permutations);
65+
// Backtrack: swap the characters back to their original positions
66+
str = swapCharacters(str, start, currentIndex);
4867
}
4968
}
5069
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.thealgorithms.strings;
2+
import org.junit.jupiter.params.ParameterizedTest;
3+
import org.junit.jupiter.params.provider.MethodSource;
4+
5+
import java.util.HashSet;
6+
import java.util.Set;
7+
import java.util.stream.Stream;
8+
9+
import static org.junit.jupiter.api.Assertions.assertEquals;
10+
11+
public class PermuteStringTest {
12+
13+
private Set<String> getPermutations(String str) {
14+
Set<String> permutations = new HashSet<>();
15+
PermuteString.generatePermutations(str, 0, str.length(), permutations);
16+
return permutations;
17+
}
18+
19+
private static Stream<TestData> provideTestCases() {
20+
return Stream.of(new TestData("ABC", Set.of("ABC", "ACB", "BAC", "BCA", "CAB", "CBA")), new TestData("AB", Set.of("AB", "BA")), new TestData("A", Set.of("A")), new TestData("AA", Set.of("AA")),
21+
new TestData("123", Set.of("123", "132", "213", "231", "312", "321")), new TestData("aA", Set.of("aA", "Aa")), new TestData("AaB", Set.of("AaB", "ABa", "aAB", "aBA", "BAa", "BaA")),
22+
new TestData("!@", Set.of("!@", "@!")), new TestData("!a@", Set.of("!a@", "!@a", "a!@", "a@!", "@!a", "@a!")), new TestData("ABCD", Set.of("ABCD", "ABDC", "ACBD", "ACDB", "ADBC", "ADCB", "BACD",
23+
"BADC", "BCAD", "BCDA", "BDAC", "BDCA", "CABD", "CADB", "CBAD", "CBDA", "CDAB", "CDBA", "DABC", "DACB", "DBAC", "DBCA", "DCAB", "DCBA")), new TestData("A B", Set.of("A B", "AB ", " AB", " BA", "BA ", "B A")),
24+
new TestData("abcd", Set.of("abcd", "abdc", "acbd", "acdb", "adbc", "adcb", "bacd", "badc", "bcad", "bcda", "bdac", "bdca", "cabd", "cadb", "cbad", "cbda", "cdab", "cdba", "dabc", "dacb", "dbac", "dbca", "dcab", "dcba"))
25+
);
26+
}
27+
28+
@ParameterizedTest
29+
@MethodSource("provideTestCases")
30+
void testPermutations(TestData testData) {
31+
Set<String> actualPermutations = getPermutations(testData.input);
32+
assertEquals(testData.expected, actualPermutations, "The permutations of '" + testData.input + "' are not correct.");
33+
}
34+
35+
record TestData(String input, Set<String> expected) {
36+
}
37+
}

0 commit comments

Comments
 (0)