Generate Permutations
Given an array of distinct integers, return all permutations — every ordering of the elements. The classic backtracking template builds a path, marks elements with a used array, and backtracks by undoing each choice. This lesson covers the algorithm, swap variant, LeetCode 46/47, and implementations in C, Java, and Python with trace tables.
Overview
A permutation is a rearrangement of all elements. For n distinct items there are n! permutations. Backtracking explores a decision tree: at each level, pick an unused element, go deeper, then undo.
nums = [1, 2, 3] — decision tree (first branch shown)
[]
/ | \
1 2 3
/|\ /|\ /|\
2 3 1 3 1 2
| | | | | |
[1,2,3] ... [3,2,1]
6 permutations total: 3! = 6
Problem Statement
Input: Array nums of n distinct integers.
Output: All permutations — each is an array containing every element exactly once.
Example: nums = [1, 2, 3] → [[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1]]
Count: For distinct elements, answer size is n!.
Backtracking Algorithm (used + path)
- Maintain current
path(partial permutation) andused[i]flags. - Base case: if
len(path) == n, append a copy toresult. - For each index
iwhereused[i] == false:- Mark
used[i] = true, appendnums[i]topath. - Recurse.
- Backtrack: remove last element, set
used[i] = false.
- Mark
isValid needed when all elements are distinct — the used array prevents duplicates in the same path.Swap Approach
Fix position start and swap nums[start] with each nums[i] where i ≥ start. Recurse on start + 1, then swap back.
- Builds permutations in-place — no separate
pathlist. - When
start == n, record a copy ofnums. - Common in C/C++ interviews; same O(n!) time.
Code (C, Java, Python)
Python
def permute(nums):
"""All permutations — backtracking with used[] and path."""
n = len(nums)
used = [False] * n
path = []
result = []
def backtrack():
if len(path) == n:
result.append(path[:])
return
for i in range(n):
if used[i]:
continue
used[i] = True
path.append(nums[i])
backtrack()
path.pop()
used[i] = False
backtrack()
return result
if __name__ == "__main__":
print(permute([1, 2, 3])) # 6 permutations
Java
import java.util.ArrayList;
import java.util.List;
public class Permutations {
public static void backtrack(int[] nums, boolean[] used, List<Integer> path,
List<List<Integer>> result) {
if (path.size() == nums.length) {
result.add(new ArrayList<>(path));
return;
}
for (int i = 0; i < nums.length; i++) {
if (used[i]) continue;
used[i] = true;
path.add(nums[i]);
backtrack(nums, used, path, result);
path.remove(path.size() - 1);
used[i] = false;
}
}
public static List<List<Integer>> permute(int[] nums) {
List<List<Integer>> result = new ArrayList<>();
backtrack(nums, new boolean[nums.length], new ArrayList<>(), result);
return result;
}
public static void main(String[] args) {
System.out.println(permute(new int[]{1, 2, 3}).size()); // 6
}
}
C (swap approach)
#include <stdio.h>
#include <stdlib.h>
void swap(int *a, int *b) { int t = *a; *a = *b; *b = t; }
void permute_swap(int nums[], int start, int n, int *count) {
int i;
if (start == n) { (*count)++; return; }
for (i = start; i < n; i++) {
swap(&nums[start], &nums[i]);
permute_swap(nums, start + 1, n, count);
swap(&nums[start], &nums[i]);
}
}
int main(void) {
int nums[] = {1, 2, 3}, count = 0;
permute_swap(nums, 0, 3, &count);
printf("%d\n", count); /* 6 */
return 0;
}
Output & Trace
All permutations for nums = [1, 2, 3]
| # | Permutation |
|---|---|
| 1 | [1, 2, 3] |
| 2 | [1, 3, 2] |
| 3 | [2, 1, 3] |
| 4 | [2, 3, 1] |
| 5 | [3, 1, 2] |
| 6 | [3, 2, 1] |
Partial trace — used + path for [1, 2, 3]
| Step | Choice | path | Action |
|---|---|---|---|
| 1 | pick 1 | [1] | used[0]=true, recurse |
| 2 | pick 2 | [1,2] | used[1]=true, recurse |
| 3 | pick 3 | [1,2,3] | Record permutation #1 |
| 4 | undo 3 | [1,2] | pop, used[2]=false |
| 5 | pick 3 | [1,3] | After undo 2, try 3 next |
| 6 | pick 2 | [1,3,2] | Record permutation #2 |
| 7 | … | … | Continue until all 6 found |
Permutation counts
| n | n! | Count |
|---|---|---|
| 1 | 1! | 1 |
| 2 | 2! | 2 |
| 3 | 3! | 6 |
| 4 | 4! | 24 |
LeetCode 46 & 47
| Problem | Input | Extra handling |
|---|---|---|
| 46 — Permutations | Distinct integers | Standard used[] backtracking |
| 47 — Permutations II | May contain duplicates | Sort nums; skip when nums[i]==nums[i-1] and !used[i-1] |
i > 0 and nums[i] == nums[i-1] and used[i-1] == false, skip — avoids generating duplicate permutations at the same tree level.Optimizations
- Swap in-place: Avoids copying path; good for memory in C/C++.
- next_permutation (C++): Iterative O(n!) generation after sorting once.
- Bitmask used set: Compact
usedas an integer bitmask for small n. - Early stop: If only one permutation needed, stop at first base case.
Approach Comparison
| Approach | Time | Space | Notes |
|---|---|---|---|
| used[] + path | O(n · n!) | O(n) recursion + path | Most readable; default interview |
| Swap backtracking | O(n · n!) | O(n) recursion | In-place; common in C |
| next_permutation | O(n · n!) | O(1) extra | C++ STL; not recursive |
Real-Life Applications
| Domain | Scenario | Mapping |
|---|---|---|
| Anagrams | Find all rearrangements of a word | Permutations of character multiset |
| Scheduling | Try all task orderings | Each ordering is a permutation |
| Testing | Exhaustive input order tests | Generate all orderings of test cases |
| Cryptography | Brute-force key permutations | Search space exploration |
| Combinatorics | Count/list arrangements | Foundation for combinations subsets |
Interview Tips
- State the count upfront:
ndistinct →n!permutations. - Write the used[] template — interviewers recognize it instantly.
- At base case, append
path.copy()/new ArrayList<>(path), not the live path. - Mention swap variant if asked for in-place or C-style solution.
- For duplicates, mention sort + skip-same-at-level rule (LC 47).
- Contrast with combinations — permutations care about order; combinations do not.
Key Takeaway
Generate permutations = backtrack with used[] and path: pick each unused element, recurse, then undo. n distinct elements → n! results. Swap approach builds the same tree in-place.
Next up: Generate combinations · Pruning techniques · Backtracking introduction