Backtracking — Next Permutation
↗ LeetCode: Next Permutation · Medium · pattern chapter →
Rearrange nums to the next lexicographic permutation in-place. If none, sort ascending.
Example 1 — nums=[1,2,3] → [1,3,2]Example 2 — nums=[3,2,1] → [1,2,3] (last perm → wrap to first) Example 3 — nums=[1,1,5] → [1,5,1]
Constraints — 1 ≤ n ≤ 100. Brute enumerate all n! permutations + sort + look up next is O(n! · n log n) — 100! is beyond universe. Classic in-place algorithm is O(n). Brute generates all n! permutations then finds next — 10¹⁶⁵ ops at n=100 (dies). Linear scan from right to find pivot + swap + reverse suffix is O(n) = 100 ops.
⏱️Interview timer00:00
Approach 1 — Enumerate all n! permutations
Intuition. Generate all permutations in lex order (or sort them). Find the current one. Return the next.
Complexity — Time O(n! · n); Space O(n! · n). Beyond n=10. In an interview say "there's a beautiful O(n) in-place algorithm — pivot-swap-reverse."
Approach 2 — Classic algorithm (canonical)
Insight — 3-step pivot-swap-reverse:
- Scan from right; find first
iwithnums[i] < nums[i+1](pivot). If none, whole array is decreasing → reverse to ascending. - Scan from right; find first
jwithnums[j] > nums[i]. Swapiandj. - Reverse suffix from
i+1to end (was decreasing → becomes increasing = smallest larger permutation).
void nextPermutation(int[] nums) {
int n = nums.length, i = n - 2;
while (i >= 0 && nums[i] >= nums[i + 1]) i--;
if (i >= 0) {
int j = n - 1;
while (nums[j] <= nums[i]) j--;
swap(nums, i, j);
}
reverse(nums, i + 1, n - 1);
}
void swap(int[] a, int i, int j) { int t = a[i]; a[i] = a[j]; a[j] = t; }
void reverse(int[] a, int l, int r) { while (l < r) swap(a, l++, r--); }2
3
4
5
6
7
8
9
10
11
12
Complexity — Time O(n); Space O(1). Say aloud in an interview: "same pattern in std::next_permutation in the C++ standard library, and itertools.permutations's iterative production."
Try it yourself
Complexity summary
| Approach | Time | Space | Grade |
|---|---|---|---|
| Enumerate all perms | O(n! · n) | O(n! · n) | Reference; fails past n=10 |
| Classic 3-step | O(n) | O(1) | Canonical |
When to use which
- Standard next-perm → this algorithm.
- Previous permutation → mirror the steps (scan for decreasing gap, etc).
- Kth permutation → factorial-number system.