题目:Next Permutation ##
原题链接:https://leetcode.com/problems/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, do not allocate 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
实现next_permutation算法,重新排序数组使生成下一个在字典序上较大的序列,如果无法找到更大的序列,则重新排序至最小字典序(例如变成升序排列)。
只能在数组中替换,不要使用额外的内存。
例:
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1
思路
首先看一下极端情况,即当前的序列在字典序上已经是最大的了,由于找不到比它更大的,就把它排序成最小的序列,具体怎么实现呢,只需要将这个序列反转过来即可。
根据上面的思路,来设想一下一般情况,即序列没有达到字典序最大的情况。我们可以把这个序列分成两部分,其中右部分是已经达到字典序最大的情况,剩下的是左部分。
例如:5 4 1 3 2,其中3 2这个片段已经达到的自身的字典序最大情况即右部分,剩下的 5 4 1片段则是另外一部分,即左部分。
由于右部分已经达到了字典序最大,要使整个序列生成下一个字典序较大的序列,我们就需要借助左部分的元素,来给右部分重新排序。
因为需要字典序变大,但是又必须是相邻的下一个字典序,那么就只能交换序列左部分中的最后一个元素了,即例子中的 1 ,假设为last, 同时只能在右部分中所有比last大的元素中找到最小的那个,在例子中就是2,此时交换这两个数的位置。即 5 4 2 3 1
最后一步,这个时候右部分的元素仍然是字典序最大的情况,由于我们已经交换了last,那么右部分的元素需要变成为字典序最小的情况,即反转右部分的元素。即 5 4 2 1 3.
参考代码
代码如下:
class Solution {
public:
void nextPermutation(vector<int>& nums) {
int len = nums.size();
if(len < 2) return;
int index = len - 2;
while(index >= 0) {
if(nums[index] < nums[index + 1]) break;
index--;
}
if(index == -1) {
reverse(nums.begin(), nums.end());
return;
}
int tIndex = len - 1;
while(tIndex > index){
if(nums[tIndex] > nums[index]) break;
tIndex--;
}
swap(nums[tIndex], nums[index]);
reverse(nums.begin() + index + 1, nums.end());
return;
}
};