Swiftorial Logo
Home
Swift Lessons
Matchups
CodeSnaps
Tutorials
Career
Resources
Permutations of a String

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 List permute(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!