Skip to content

Permutations

Given an array nums of distinct integers, return all the possible permutations. You can return the answer in any order.

A permutation is an arrangement of all elements where order matters: [1,2] and [2,1] are different permutations.

InputOutputExplanation
[1,2,3][[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1]]6 unique orderings (3! = 6)
[0,1][[0,1], [1,0]]2 unique orderings (2! = 2)
[1][[1]]1 unique ordering (1! = 1)
  • 1 <= nums.length <= 6
  • -10 <= nums[i] <= 10
  • All integers of nums are unique
ApproachTimeSpaceMemoryBest When
Swap (In-place)O(n! * n)O(n!)O(1) extraWant minimal extra memory, cleaner code
Used ArrayO(n! * n)O(n!)O(n) extraPrefer keeping original array unmodified
  • Pick Swap if you want an elegant, space-efficient solution.
  • Pick Used Array if you prefer a more explicit choice-explore-unchoose pattern.
Most Elegant
Swap
O(n! * n) time · O(n!) space
Most Explicit
Used Array
O(n! * n) time · O(n!) space
Section titled “Approach 1: Backtracking with Swap (Recommended)”
★ Recommended

Build permutations by treating the array as having a “fixed” portion and a “to-be-determined” portion. For each position first, try each remaining element in that position. Swap it in, recursively solve for the rest, then swap it back.

This is elegant because it requires no extra tracking data structure—the array itself tracks which elements are available.

⏱ Time O(n! * n) n! perms, n work per perm 💾 Space O(n!) Result storage

Input: nums = [1, 2, 3]

firstcurrentaction
0[1, 2, 3]Fix 1 at position 0, recurse on [2,3]
1[1, 2, 3]Fix 2 at position 1, recurse on [3]
2[1, 2, 3]Base case: save [1,2,3]
1[1, 3, 2]Swap 2 and 3, save [1,3,2]
0[2, 1, 3]Swap 1 and 2, fix 2 at position 0
1[2, 1, 3]Explore rest; save [2,1,3]
function permutationsSwap(nums):
result = []
function backtrack(first):
if first == len(nums):
result.append(copy of nums)
return
for i from first to len(nums)-1:
swap(nums[first], nums[i])
backtrack(first + 1)
swap(nums[first], nums[i]) # Backtrack
backtrack(0)
return result
permutations_swap.py
from typing import List
def permutations_swap(nums: List[int]) -> List[List[int]]:
"""
Generate all permutations using backtracking with swapping approach.
Time: O(n! * n), Space: O(n!) for result
"""
result = []
def backtrack(first: int) -> None:
# Base case: all elements are placed
if first == len(nums):
result.append(nums[:]) # Make a copy
return
for i in range(first, len(nums)):
# Swap
nums[first], nums[i] = nums[i], nums[first]
# Backtrack
backtrack(first + 1)
# Swap back
nums[first], nums[i] = nums[i], nums[first]
backtrack(0)
return result
print(permutations_swap([1, 2, 3]))
# Output: [[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1]]
🎯 Interview Favourite

Build permutations by explicitly tracking which elements have been used. Maintain a boolean array marking visited elements. For each position, try each unused element, mark it as used, recurse, then unmark it.

This approach is more explicit about the choice/explore/unchoose pattern and leaves the original array untouched.

⏱ Time O(n! * n) n! perms, n work per perm 💾 Space O(n!) Result storage + used array

Input: nums = [1, 2, 3]

currentusedaction
[1][T,F,F]Choose 1, explore [2,3]
[1,2][T,T,F]Choose 2, explore [3]
[1,2,3][T,T,T]Save [1,2,3]
[1,3][T,F,T]Unchoose 2, choose 3
[1,3,2][T,T,T]Save [1,3,2]
[2][F,T,F]Unchoose 1, choose 2
function permutationsUsedArray(nums):
result = []
used = [false] * len(nums)
current = []
function backtrack():
if len(current) == len(nums):
result.append(copy of current)
return
for i from 0 to len(nums)-1:
if used[i]:
continue
current.append(nums[i])
used[i] = true
backtrack()
current.pop()
used[i] = false
backtrack()
return result
permutations_used_array.py
from typing import List
def permutations_used_array(nums: List[int]) -> List[List[int]]:
"""
Generate all permutations using backtracking with used array.
Time: O(n! * n), Space: O(n!) for result
"""
result = []
used = [False] * len(nums)
def backtrack(current: List[int]) -> None:
# Base case: we've used all numbers
if len(current) == len(nums):
result.append(current[:]) # Make a copy
return
for i in range(len(nums)):
if used[i]:
continue
# Choose
current.append(nums[i])
used[i] = True
# Explore
backtrack(current)
# Unchoose
current.pop()
used[i] = False
backtrack([])
return result
print(permutations_used_array([1, 2, 3]))
# Output: [[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1]]
✓ Simple

A third approach demonstrating an alternative technique for solving this problem. This implementation optimizes either time or space complexity compared to the previous approaches.

⏱ Time O(n) Optimized complexity 💾 Space O(1) Efficient space usage
function approach3():
// Implementation approach goes here
permutations_space_optimized.py
"""
Solution for Permutations
"""
def solve():
"""Implementation for approach 3 of Permutations"""
pass
if __name__ == "__main__":
print("Solution ready")