leetcode 31. Next Permutation
Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers.
If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order).
The replacement must be in-place and use only constant extra memory.
Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column.
1,2,3
→ 1,3,2
3,2,1
→ 1,2,3
1,1,5
→ 1,5,1
题目大意:按照字典序生成排列,给定一个排列,生成下一个排列。
首先,我们观察到,对于任何按降序排列的给定序列,都不可能出现下一个更大的排列。例如,下面的数组不可能有下一个排列:
[9,5,4,3,1]
我们需要从右边找到满足a[i]>a[i -1]的两个连续数字a[i]和a[i-1]的前一对。现在,a[i-1]右边的任何重新排列都不能产生更大的排列,因为该子数组由降序数字组成。因此,我们需要把数字重新排列到a[i-1]包括它自身的右边。
那么,什么样的重新排列会产生下一个更大的数呢?我们想要创建一个比当前更大的置换。因此,我们需要将数字a[i-1]替换为数字a[j]。a[j]为i - 1后大于a[i - 1]的最小数。
我们交换数字a[i -1]和a[j]。但目前的排列仍然不是我们要找的排列。我们需要一种最小的排列,这种排列只能由a[i-1]右边的数组成。因此,我们需要将这些数字按升序排列,以得到它们最小的排列。
但是,请记住,当我们从右边扫描这些数字时,我们只是不断地减小索引,直到找到a[i]和a[i−1]对,其中a[i]>a[i−1]。因此,a[i-1]右边的所有数都已按降序排列。此外,交换a[i-1]和a[j]并没有改变顺序。因此,我们只需要将a[i-1]后面的数字倒转,就可以得到下一个最小的词典排列。
1 class Solution { 2 public: 3 void nextPermutation(vector<int>& nums) { 4 int i = nums.size() - 2; 5 while (i >= 0 && nums[i] >= nums[i + 1]) { 6 --i; 7 } 8 if (i >= 0) { 9 int j = nums.size() - 1; 10 while (nums[j] <= nums[i]) { 11 --j; 12 } 13 swap(nums[i], nums[j]); 14 } 15 reverse(nums, i + 1, nums.size() - 1); 16 } 17 private: 18 void reverse(vector<int> &nums, int start, int end) { 19 while (start < end) { 20 swap(nums[start++], nums[end--]); 21 } 22 } 23 };