We want all permutations of nums, i.e. all possible orderings.
This is a classic backtracking problem.
There are two main ways to generate permutations:
- Method 1: Backtracking with
used[] + path(build path explicitly) - Method 2: Backtracking with in-place
swap(modify nums directly)
Both generate n! permutations, but they differ in space usage & runtime performance.
- Maintain a separate
pathlist for the current permutation. - Track visited elements with a
used[]boolean array. - At each step, iterate over all unused elements, append to
path, recurse, then pop back.
- Time: O(n·n!) – each recursion level tries all possible elements
- Space: O(n) recursion depth + O(n) for
used[]+ O(n!) for results
- Cache-friendly: elements in
numsremain in original order - No extra swap overhead, just
push_backandpop_back - Typically faster in practice on LeetCode, runtime ~100%
- Instead of a
used[]array, fix one position at a time by swapping elements. - At recursion depth
place, swapnums[place]with each possible candidate. - After recursion, swap back to restore original state.
- Time: O(n·n!) – same theoretical complexity
- Space: O(n) recursion depth + O(n!) for results
- But introduces extra overhead from swap calls
- More swaps → O(n·n!) swap operations
- Worse cache locality because
numsis constantly rearranged - Copying the entire
numsinto results is less predictable for CPU cache - Typically slower in practice, LeetCode runtime ~37.5%
| Feature | Method 1: used[] + path |
Method 2: swap in-place |
|---|---|---|
| Extra space | O(n) | O(1) |
| Backtrack cleanup | Pop + mark used=false |
Extra swap per step |
| Cache friendliness | ✅ better | ❌ worse (nums scrambled) |
| Constant overhead | Low (push/pop) | High (2 swaps per call) |
| Runtime (LeetCode) | ~100% (faster) | ~37.5% (slower) |
| Memory efficiency | Slightly worse (used[]) | Slightly better |
- Both approaches have identical theoretical complexity O(n·n!).
- The swap version saves an extra
used[]array, but adds more swap operations, which increases runtime overhead. - The
used[]+ path version is more cache-friendly, since the originalnumsorder stays stable. - On LeetCode, runtime differences often come from constant factors (swaps vs push/pop) and CPU cache behavior, not big-O complexity.
- Recommendation: if you care about runtime ranking, prefer
used[] + path; if you want minimal extra memory,swapis acceptable.