By Fatskills Exam Guides Team — the exam nerds behind 28,500+ quizzes and 2.1M practice questions across 500+ global exams.
"Permutations appear in 1 out of every 3 onsite interviews—master this, and you’ll prove you can handle recursion, backtracking, and edge cases like a senior engineer."
Before tackling permutations, ensure you understand: 1. Recursion & Backtracking – Breaking problems into smaller subproblems and undoing choices. 2. Hash Sets / Frequency Maps – Tracking used elements (especially for duplicates). 3. Time Complexity of Recursive Algorithms – How to analyze O(n!) and pruning optimizations.
O(n!)
if i > 0 and nums[i] == nums[i-1] and not used[i-1]
visited
nums[i]
nums[start]
next_permutation
std::next_permutation
Follow these steps for every permutation problem:
Are there constraints (e.g., max length, sum conditions)?
Choose a Base Approach
Space optimization? → In-place swapping (no extra visited array).
Define the Recursive Function
start
path
start == len(nums)
Recursive Case:
Handle Duplicates (If Applicable)
Skip duplicates by checking: python if i > start and nums[i] == nums[i-1]: continue
python if i > start and nums[i] == nums[i-1]: continue
Optimize for Edge Cases
[[]]
[[nums[0]]]
Large input? → Consider iterative DFS if recursion depth is a concern.
Analyze Time & Space Complexity
O(n! / (k1! k2! ...))
Space: O(n) (recursion stack) or O(n!) (if storing all results).
O(n)
Test with Examples
[1,2,3]
[1,1,2]
Problem: Given an array nums with unique elements, return all possible permutations.
nums
[[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1]]
def permute(nums): def backtrack(start): if start == len(nums): result.append(nums.copy()) return for i in range(start, len(nums)): nums[start], nums[i] = nums[i], nums[start] # Swap backtrack(start + 1) nums[start], nums[i] = nums[i], nums[start] # Swap back result = [] backtrack(0) return result
Problem: Given an array nums with duplicates, return all unique permutations.
[[1,1,2], [1,2,1], [2,1,1]]
if i > start and nums[i] == nums[i-1]
def permuteUnique(nums): def backtrack(start): if start == len(nums): result.append(nums.copy()) return for i in range(start, len(nums)): if i > start and nums[i] == nums[i-1]: continue # Skip duplicates nums[start], nums[i] = nums[i], nums[start] backtrack(start + 1) nums[start], nums[i] = nums[i], nums[start] nums.sort() # Sort to group duplicates result = [] backtrack(0) return result
Problem: Given nums and a target k, return all permutations where the sum of elements equals k.
k
nums = [1,2,3]
k = 3
[[1,2], [2,1], [3]]
def permutationSum(nums, k): def backtrack(start, path, current_sum): if current_sum == k: result.append(path.copy()) return for i in range(len(nums)): if used[i] or current_sum + nums[i] > k: continue # Skip used or invalid sums used[i] = True path.append(nums[i]) backtrack(i + 1, path, current_sum + nums[i]) path.pop() used[i] = False nums.sort() # Optional: helps with pruning result = [] used = [False] len(nums) backtrack(0, [], 0) return result
used
current_sum > k
nums = []
"Here’s your 60-second cheat sheet for permutations: 1. Unique elements? Use backtracking with swapping or a visited array. 2. Duplicates? Sort first, then skip duplicates in recursion. 3. Constraints? Prune early (e.g., sum checks). 4. Edge cases? Test empty input, single element, and duplicates. 5. Time complexity? O(n!) for unique, fewer for duplicates. 6. Space? O(n) for recursion stack, O(n!) if storing results.
Walk in confident—you’ve got this!
Now go ace that interview! ?
Join 4M+ learners. Unlock unlimited quizzes, wrong-answer tracking, flashcards + reminders, study guides, and 1-on-1 challenges.