The problem. Given an array nums of distinct integers, return all the possible permutations (orderings), in any order.
nums = [1, 2, 3] -> [[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1]]
nums = [0, 1] -> [[0,1], [1,0]]
nums = [1] -> [[1]]Here order matters, so the start-index trick from the last chapter no longer applies: after choosing 2, choosing 1 is still allowed. Instead each level may pick any value not used yet, tracked with a used array. The same chapter covers building strings under rules — valid brackets, palindromic pieces — where the rule decides which choices are allowed at each step.
Each level tries every number not used yet; un-choosing frees it for the next branch.
function permute(nums) { const result = []; const path = []; const used = new Array(nums.length).fill(false); const build = () => { if (path.length === nums.length) { // every number placed: one permutation result.push([...path]); return; } for (let i = 0; i < nums.length; i++) { if (used[i]) continue; // already in the path used[i] = true; // choose path.push(nums[i]); build(); // explore path.pop(); // un-choose used[i] = false; } }; build(); return result;}Time O(n · n!): n! leaves, each copied in O(n). Space O(n) for the path, the used array and the call stack, besides the output.
Instead of a separate path, build the permutation inside the array: position i takes each value from i onwards in turn by swapping it in, the rest is permuted recursively, then the swap is undone.
function permute(nums) { const a = [...nums]; const result = []; const fill = (i) => { if (i === a.length) { result.push([...a]); return; } for (let j = i; j < a.length; j++) { [a[i], a[j]] = [a[j], a[i]]; // put a[j] at position i fill(i + 1); [a[i], a[j]] = [a[j], a[i]]; // swap back } }; fill(0); return result;}Time O(n · n!), space O(n) — no used array or separate path. The permutations come out in a different order, which the problem allows.