150NeetCode 150

73.Permutations

MediumBacktracking · 3/9

Problem

Given an array nums of distinct integers, return all possible permutations — every ordering of all the elements. The answer may be returned in any order.

Examples

Input:  nums = [1, 2, 3]
Output: [[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1]]
Explanation: 3 distinct elements have 3! = 6 orderings.
Input:  nums = [0, 1]
Output: [[0,1], [1,0]]
Input:  nums = [1]
Output: [[1]]

Constraints

  • 1 <= nums.length <= 6
  • -10 <= nums[i] <= 10
  • All the integers of nums are unique.

💡 Key Insight

Build a permutation one position at a time: the first slot has n choices, the next n - 1, and so on, giving n! leaves. The only thing to track is which elements are already used — a boolean[] used array, or swapping elements into a prefix of the array so the "unused" ones are always the suffix.

Insertion (Iterative)

TimeO(n · n!)SpaceO(n · n!)

Intuition

Every permutation of [1..k] is obtained by taking a permutation of [1..k-1] and inserting element k into one of its k gaps. Start from [[]] and grow.

Algorithm

  1. perms = [[]].
  2. For each num in nums:
    • next = [].
    • For every p in perms and every position pos in 0..p.size(): copy p, insert num at pos, add to next.
    • perms = next.
  3. Return perms.

Visualization

start      : [[]]
insert 1   : [[1]]
insert 2   : [[2,1], [1,2]]
insert 3   : [[3,2,1], [2,3,1], [2,1,3], [3,1,2], [1,3,2], [1,2,3]]

Code

java
import java.util.*;

class Solution {
    public List<List<Integer>> permute(int[] nums) {
        List<List<Integer>> perms = new ArrayList<>();
        perms.add(new ArrayList<>());
        for (int num : nums) {
            List<List<Integer>> next = new ArrayList<>();
            for (List<Integer> p : perms) {
                // insert num into every gap of p (including both ends)
                for (int pos = 0; pos <= p.size(); pos++) {
                    List<Integer> copy = new ArrayList<>(p);
                    copy.add(pos, num);
                    next.add(copy);
                }
            }
            perms = next;
        }
        return perms;
    }
}

Complexity

  • Time: O(n · n!) — the last round builds n! lists of length n; earlier rounds are smaller.
  • Space: O(n · n!) — the intermediate lists of the previous round plus the output.

Complexity Comparison

Approach Time Space (extra)
Insertion O(n · n!) O(n · n!)
Backtracking + used[] O(n · n!) O(n)
In-place Swapping O(n · n!) O(n)

Common Pitfalls

  • Forgetting to reset used[i] = false after the recursive call — later branches never see that element again.
  • Forgetting the second swap — the array is left scrambled and later permutations repeat or go missing.
  • Adding path instead of a copy of it.
  • Starting the inner loop at start with a used array (that is the combinations pattern) — permutations need every unused index, from 0.