Permutations
Given an array of distinct integers, return every possible ordering of those integers.
Every permutation uses all of the elements exactly once — none omitted, none repeated. Two permutations differ if the elements appear in a different sequence, so [1,2,3] and [2,1,3] are both valid and distinct answers.
The output contains n! permutations and may be returned in any order.
- 1 <= nums.length <= 6
- -10 <= nums[i] <= 10
- All integers in nums are distinct
- Every permutation must use every element exactly once
- Output size is n!, which is 720 at the maximum input length
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]]nums = [-1,2,-3]All 6 orderings of -1, 2 and -3An arrangement uses every element, and order is the answer — [1,2,3] and [2,1,3] are both wanted. So there's no "increasing only" trick here (that would throw away answers we need). Instead, at each slot pick any element not already used.
Every problem in this section is the same loop — three beats: choose, explore, un-choose.
def backtrack(state):
if done(state):
save(state) # record the finished answer
return
for choice in choices(state): # what can I pick right now?
if not ok(choice):
continue # prune: skip bad picks early
apply(choice) # CHOOSE
backtrack(next_state) # EXPLORE
undo(choice) # UN-CHOOSE: put it backOnly four slots change between problems: done, choices, ok (pruning), and how you finish (save every answer, or return True at the first one). Fill those and the problem is solved.
i with used[i] == False.n → save it.def permute(nums):
res, path = [], []
used = [False] * len(nums)
def backtrack():
if len(path) == len(nums):
res.append(list(path))
return
for i in range(len(nums)):
if used[i]:
continue # already placed
used[i] = True # CHOOSE
path.append(nums[i])
backtrack() # EXPLORE
path.pop() # UN-CHOOSE
used[i] = False # release it
backtrack()
return resUndo both things: pop the path and set used[i] = False. Forgetting the release is the classic bug — elements get eaten and you end up with almost no permutations. Note there's no start index here; looping from 0 every time is exactly what produces the reorderings.
Trace [1,2,3]: fix 1 → [1,2,3],[1,3,2]; fix 2 → [2,1,3],[2,3,1]; fix 3 → [3,1,2],[3,2,1]. n! = 6.
The Arrangement Tree
Visualizing how the seating chart evolves with each pick.
THE USED POOL
Once a number is in a chair, it's Busy. We can't pick it again until it "stands up" (backtracks) and becomes Available once more.
ORDER MATTERS
Unlike subsets, picking [1, 2] and [2, 1] are two completely different realities. Every branch of the tree must lead to a full line-up.