Permutations of a String
Problem Statement
Given a string, generate all possible permutations of its characters. A permutation is a rearrangement of the string’s characters, and all must be unique if the string has duplicates. This medium-level problem dives into recursion and backtracking, exploring every possible order of characters—think of it as shuffling a deck of letters to see all combinations!
Example
Input: s = "abc"
Output: ["abc", "acb", "bac", "bca", "cab", "cba"] (all 3! = 6 permutations)
Input: s = "aab"
Output: ["aab", "aba", "baa"] (3 unique permutations due to duplicates)
Code
Java
Python
JavaScript
public class Solution { public Listpermute(String s) { List result = new ArrayList<>(); char[] chars = s.toCharArray(); backtrack(chars, 0, result); return result; } private void backtrack(char[] chars, int start, List result) { if (start == chars.length) { result.add(new String(chars)); return; } Set used = new HashSet<>(); for (int i = start; i < chars.length; i++) { if (!used.contains(chars[i])) { used.add(chars[i]); swap(chars, start, i); backtrack(chars, start + 1, result); swap(chars, start, i); // Backtrack } } } private void swap(char[] chars, int i, int j) { char temp = chars[i]; chars[i] = chars[j]; chars[j] = temp; } }
def permute(s): def backtrack(chars, start, result): if start == len(chars): result.append("".join(chars)) return seen = set() for i in range(start, len(chars)): if chars[i] not in seen: seen.add(chars[i]) chars[start], chars[i] = chars[i], chars[start] backtrack(chars, start + 1, result) chars[start], chars[i] = chars[i], chars[start] # Backtrack result = [] backtrack(list(s), 0, result) return result # Example usage print(permute("abc")) # ["abc", "acb", "bac", "bca", "cab", "cba"] print(permute("aab")) # ["aab", "aba", "baa"]
function permute(s) { function backtrack(chars, start, result) { if (start === chars.length) { result.push(chars.join("")); return; } let seen = new Set(); for (let i = start; i < chars.length; i++) { if (!seen.has(chars[i])) { seen.add(chars[i]); [chars[start], chars[i]] = [chars[i], chars[start]]; backtrack(chars, start + 1, result); [chars[start], chars[i]] = [chars[i], chars[start]]; // Backtrack } } } let result = []; backtrack(s.split(""), 0, result); return result; } // Example usage console.log(permute("abc")); // ["abc", "acb", "bac", "bca", "cab", "cba"] console.log(permute("aab")); // ["aab", "aba", "baa"]
Explanation
- Base Case: When start reaches the string length, add the current permutation.
- Recursive Step: For each position, swap with every subsequent character and recurse.
- Backtracking: Undo swaps to restore the original state for the next iteration.
- Duplicates: Use a set to skip repeated characters at each level, ensuring unique permutations.
- Flow Example (s="ab"): Start with "ab" → swap to "ab" → recurse → "ab"; swap to "ba" → recurse → "ba".
Note
Time complexity is O(n!) for generating all permutations, where n is the string length. Space complexity is O(n!) for storing results plus O(n) for the call stack. It’s a fun combinatorial explosion!