πΉ Introduction
The permutation pattern is one of the most classic backtracking applications. It is used in:
- Arrangements (e.g., seating, task ordering).
 - String anagrams.
 - Puzzle solving (like word rearrangements).
 - Combinatorial enumeration.
 
π Interviewers love this pattern because it tests recursion, backtracking, and handling duplicates.
πΉ Core Idea
At each step:
- Choose an unused element.
 - Add it to the current sequence.
 - Recurse to place the next element.
 - Undo (backtrack).
 
πΉ Base Template (All Permutations)
import java.util.*;
public class PermutationPattern {
    public List<List<Integer>> permute(int[] nums) {
        List<List<Integer>> results = new ArrayList<>();
        boolean[] used = new boolean[nums.length];
        backtrack(new ArrayList<>(), used, nums, results);
        return results;
    }
    private void backtrack(List<Integer> current, boolean[] used, int[] nums, List<List<Integer>> results) {
        if (current.size() == nums.length) {
            results.add(new ArrayList<>(current));
            return;
        }
        for (int i = 0; i < nums.length; i++) {
            if (used[i]) continue;
            // Choose
            current.add(nums[i]);
            used[i] = true;
            // Explore
            backtrack(current, used, nums, results);
            // Undo (Backtrack)
            current.remove(current.size() - 1);
            used[i] = false;
        }
    }
}
  
  
  πΉ Recursion Tree (for [1,2,3])
            []
   /          |         \
 [1]         [2]        [3]
 / \         / \        / \
[1,2][1,3] [2,1][2,3] [3,1][3,2]
  |     |    |     |    |     |
[1,2,3][1,3,2][2,1,3][2,3,1][3,1,2][3,2,1]
π Each leaf = one valid permutation.
πΉ Variations of Permutations
Now letβs cover all interview-relevant variations.
β 1. Permutations of an Array of Distinct Integers
- Input: 
[1,2,3] - Output: All 6 permutations.
 
π Already covered with base template.
β 2. Permutations with Duplicates (Avoid Duplicates)
- Input: 
[1,1,2] - Output:
 
[1,1,2]
[1,2,1]
[2,1,1]
π Trick: Sort array + skip duplicates if previous is not used.
public List<List<Integer>> permuteUnique(int[] nums) {
    Arrays.sort(nums); // sort to handle duplicates
    List<List<Integer>> results = new ArrayList<>();
    boolean[] used = new boolean[nums.length];
    backtrackDup(new ArrayList<>(), used, nums, results);
    return results;
}
private void backtrackDup(List<Integer> current, boolean[] used, int[] nums, List<List<Integer>> results) {
    if (current.size() == nums.length) {
        results.add(new ArrayList<>(current));
        return;
    }
    for (int i = 0; i < nums.length; i++) {
        if (used[i]) continue;
        if (i > 0 && nums[i] == nums[i - 1] && !used[i - 1]) continue; // skip duplicate
        current.add(nums[i]);
        used[i] = true;
        backtrackDup(current, used, nums, results);
        current.remove(current.size() - 1);
        used[i] = false;
    }
}
β 3. String Permutations (All Anagrams)
- Input: 
"abc" - Output: 
"abc", "acb", "bac", "bca", "cab", "cba" 
public List<String> permuteString(String s) {
    List<String> results = new ArrayList<>();
    boolean[] used = new boolean[s.length()];
    backtrack(new StringBuilder(), used, s.toCharArray(), results);
    return results;
}
private void backtrack(StringBuilder current, boolean[] used, char[] chars, List<String> results) {
    if (current.length() == chars.length) {
        results.add(current.toString());
        return;
    }
    for (int i = 0; i < chars.length; i++) {
        if (used[i]) continue;
        current.append(chars[i]);
        used[i] = true;
        backtrack(current, used, chars, results);
        current.deleteCharAt(current.length() - 1);
        used[i] = false;
    }
}
β 4. String Permutations with Duplicates (Unique Anagrams)
- Input: 
"aab" - Output: 
"aab", "aba", "baa" 
(Same duplicate handling logic as arrays β sort + skip duplicates.)
β 5. Next Lexicographical Permutation (LeetCode #31)
Instead of generating all, return the next greater permutation.
public void nextPermutation(int[] nums) {
    int i = nums.length - 2;
    while (i >= 0 && nums[i] >= nums[i + 1]) i--;
    if (i >= 0) {
        int j = nums.length - 1;
        while (nums[j] <= nums[i]) j--;
        swap(nums, i, j);
    }
    reverse(nums, i + 1, nums.length - 1);
}
private void swap(int[] nums, int i, int j) {
    int temp = nums[i];
    nums[i] = nums[j];
    nums[j] = temp;
}
private void reverse(int[] nums, int i, int j) {
    while (i < j) swap(nums, i++, j--);
}
π Commonly asked in Google & Amazon interviews.
β 6. k-Permutations (Partial Permutations)
- Input: 
[1,2,3], k=2 - Output: 
[1,2], [1,3], [2,1], [2,3], [3,1], [3,2] 
private void backtrackK(List<Integer> current, boolean[] used, int[] nums, int k, List<List<Integer>> results) {
    if (current.size() == k) {
        results.add(new ArrayList<>(current));
        return;
    }
    for (int i = 0; i < nums.length; i++) {
        if (used[i]) continue;
        current.add(nums[i]);
        used[i] = true;
        backtrackK(current, used, nums, k, results);
        current.remove(current.size() - 1);
        used[i] = false;
    }
}
πΉ Complexity Analysis
- 
Time: 
O(n! * n)(since we generaten!permutations, each copied in O(n)). - 
Space: 
O(n)recursion +O(n)used array. 
πΉ Interview References
- LeetCode #46 β Permutations
 - LeetCode #47 β Permutations II (duplicates)
 - LeetCode #31 β Next Permutation
 - Asked in Google, Amazon, Facebook, Microsoft, Uber
 
πΉ Key Takeaways
β
 Subsets β include/exclude choices
β
 Permutations β arrange all elements once
β
 Duplicates β sort + skip
β
 Strings & arrays β same logic
β
 Always remember: n! growth β heavy recursion
πΉ Whatβs Next?
In Blog 4: Combination & Combinatorial Search, weβll cover:
- k-Combinations (choose k out of n)
 - Combination Sum I, II, III
 - Letter Case Permutations
 - Palindrome Partitioning
 
    
Top comments (0)