Next Permutation
Rearrange to the lexicographically next greater permutation; wrap to lowest if impossible.
4 min read
two-pointers array permutation
Problem#
In place, rearrange nums to the lexicographically next greater permutation. If the array is the largest permutation (descending), rearrange to the smallest (ascending).
Examples#
[1,2,3]→[1,3,2][3,2,1]→[1,2,3][1,1,5]→[1,5,1]
Constraints#
1 <= nums.length <= 100.
Hints#
Hint 1
Find the first descending step from the right (the “pivot”). Swap it with the next larger value to its right, then reverse the suffix.
Approach#
- Scan from the right to find pivot
iwherenums[i] < nums[i+1]. If none, the array is fully descending — reverse to smallest. - Else, scan from the right to find the smallest
nums[j] > nums[i]. Swap them. - Reverse
nums[i+1..end](it was descending; reversing makes it ascending, hence the smallest possible suffix).
Solution#
class Solution {public: void nextPermutation(vector<int>& nums) { const int n = nums.size(); int 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], nums[j]); } reverse(nums.begin() + i + 1, nums.end()); }};func nextPermutation(nums []int) { n := len(nums) i := n - 2 for i >= 0 && nums[i] >= nums[i+1] { i-- } if i >= 0 { j := n - 1 for nums[j] <= nums[i] { j-- } nums[i], nums[j] = nums[j], nums[i] } for l, r := i+1, n-1; l < r; l, r = l+1, r-1 { nums[l], nums[r] = nums[r], nums[l] }}from typing import List
class Solution: def nextPermutation(self, nums: List[int]) -> None: n = len(nums) i = n - 2 while i >= 0 and nums[i] >= nums[i + 1]: i -= 1 if i >= 0: j = n - 1 while nums[j] <= nums[i]: j -= 1 nums[i], nums[j] = nums[j], nums[i] l, r = i + 1, n - 1 while l < r: nums[l], nums[r] = nums[r], nums[l] l += 1 r -= 1function nextPermutation(nums) { const n = nums.length; let i = n - 2; while (i >= 0 && nums[i] >= nums[i + 1]) i--; if (i >= 0) { let j = n - 1; while (nums[j] <= nums[i]) j--; [nums[i], nums[j]] = [nums[j], nums[i]]; } let l = i + 1, r = n - 1; while (l < r) { [nums[l], nums[r]] = [nums[r], nums[l]]; l++; r--; }}class Solution { public void nextPermutation(int[] nums) { int n = nums.length; int 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--; int tmp = nums[i]; nums[i] = nums[j]; nums[j] = tmp; } int l = i + 1, r = n - 1; while (l < r) { int t = nums[l]; nums[l] = nums[r]; nums[r] = t; l++; r--; } }}function nextPermutation(nums: number[]): void { const n = nums.length; let i = n - 2; while (i >= 0 && nums[i] >= nums[i + 1]) i--; if (i >= 0) { let j = n - 1; while (nums[j] <= nums[i]) j--; [nums[i], nums[j]] = [nums[j], nums[i]]; } let l = i + 1, r = n - 1; while (l < r) { [nums[l], nums[r]] = [nums[r], nums[l]]; l++; r--; }}Editorial#
The pivot i is the unique position where increasing changes the rank. Everything to its right is non-increasing, so the smallest possible value strictly greater than nums[i] in that suffix swaps in cleanly (the swap preserves the descending order of the suffix). Reversing the suffix then converts it to ascending — the smallest possible tail given the new prefix. If no pivot exists, the array is the largest permutation and we wrap to ascending.
Complexity#
- Time: O(n).
- Space: O(1).
Concept revision#
Related#