47. Permutations
mediumAsked at SnowflakeGenerate all permutations of a distinct-integer array. Snowflake asks this to test backtracking with a used-mask — relevant for join-order enumeration where the planner permutes table orderings to find the optimal plan.
By Alex Chen, Founder, InterviewChamp.AI · Last verified
Source citations
Public interview reports confirming this problem appears in Snowflake loops.
- Glassdoor (2026-Q1)— Snowflake compiler-team uses this to anchor join-order enumeration discussion.
- LeetCode Discuss (2025-11)— Recurring at Snowflake new-grad onsites.
Problem
Given an array nums of distinct integers, return all the possible permutations. You can return the answer in any order.
Constraints
1 <= nums.length <= 6-10 <= nums[i] <= 10All the integers of nums are unique.
Examples
Example 1
nums = [1,2,3][[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]Example 2
nums = [0,1][[0,1],[1,0]]Approaches
1. Insert into every position
Recursively, take the first element, insert into every position of every recursively-generated permutation of the rest.
- Time
- O(n! * n)
- Space
- O(n! * n)
function permute(nums) {
if (nums.length <= 1) return [nums.slice()];
const result = [];
const subs = permute(nums.slice(1));
for (const sub of subs) {
for (let i = 0; i <= sub.length; i++) {
const p = [...sub.slice(0, i), nums[0], ...sub.slice(i)];
result.push(p);
}
}
return result;
}Tradeoff: Correct but allocates many intermediates. Mention as an alternative.
2. Backtracking with used-mask (optimal)
Maintain a path and a boolean used[] array. Recurse choosing any unused index; mark used; recurse; unmark on return.
- Time
- O(n! * n)
- Space
- O(n) recursion
function permute(nums) {
const result = [];
const used = new Array(nums.length).fill(false);
function dfs(path) {
if (path.length === nums.length) {
result.push([...path]);
return;
}
for (let i = 0; i < nums.length; i++) {
if (used[i]) continue;
used[i] = true;
path.push(nums[i]);
dfs(path);
path.pop();
used[i] = false;
}
}
dfs([]);
return result;
}Tradeoff: Minimal allocation per call. Same pattern as join-order enumeration in a planner.
Snowflake-specific tips
Snowflake interviewers want the used-mask version because it directly mirrors join-order enumeration. Bonus signal: discuss dynamic-programming-with-bitmask join-order optimization (Selinger-style) and how it caches subplan costs keyed on the bitmask of joined tables.
Common mistakes
- Forgetting to unmark used[i] on return — corrupts subsequent iterations.
- Pushing path itself instead of a copy — all results share the same mutated array.
- Sorting the input to dedup, missing that the problem says distinct.
Follow-up questions
An interviewer at Snowflake may pivot to one of these next:
- Permutations II (LC 47) — with duplicates.
- Next Permutation (LC 31) — lex next.
- Selinger join-order optimization with bitmask DP.
Solve it now
Free. No sign-up. Python and JavaScript run instantly in your browser.
FAQ
Why used[] instead of removing from input?
Mutating the input via splice is O(n) per operation and harder to undo. used[] is O(1) per check/set.
How does this connect to join ordering?
A SQL planner enumerating join orders is essentially permuting tables. Bitmask DP caches the best plan for each subset of tables, making System R's O(n!) into O(2^n * n) — still expensive, but tractable.
Practice these live with InterviewChamp.AI
Drill Permutations and other Snowflake interview questions under real-loop conditions with instant feedback on your reasoning, complexity claims, and code.
Practice these live with InterviewChamp.AI →