题目描述
实现获取 下一个排列 的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。
如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。
必须 原地 修改,只允许使用额外常数空间。
来源:力扣(LeetCode)
题目分析
字典序排列,只允许使用常数空间。最初思路即为建立字典树,进行遍历,但时间内存超限不可行
题解:学习(powcai)大神的思路
字典序的排列,是从最后往前的变动,因此选择从后往前查找,具体操作为:
1、先找出最大的索引 k 满足 nums[k] < nums[k+1],如果不存在,就翻转整个数组;
2、再找出另一个最大索引 l 满足 nums[l] > nums[k];
3、交换 nums[l] 和 nums[k];
4、最后翻转 nums[k+1:]。
void nextPermutation(vector<int>& nums) {
cout<<endl;
int len, i, j, tmp;
len = nums.size();
if(len <= 1) return;
// 首先查找到第一个nums[k] < nums[k+1]的位置
for(i = len - 2; (i>= 0)&&(nums[i] >= nums[i+1]); i--);
// 若i<0,表示遍历至头部,直接翻转整个vector
if (i < 0){
// 采用sort进行从小到大的排序,来实现翻转
sort(nums.begin(), nums.end());
return;
}
// 从后往前找到第一个大于nums[i]的位置
for(j = nums.size()-1; nums[j]<=nums[i];j--);
// 交换两个值
tmp = nums[i]; nums[i] = nums[j]; nums[j] = tmp;
// 对i之后的值进行排序
sort(nums.begin() + i + 1, nums.end());
return;
}