思路:
因为数组变化的幅度要尽可能的小,所以我们需要在数组靠右边部分操作(交换数值)。
方法:两遍扫描
我们需要将一个左边的「较小数」与一个右边的「较大数」交换,以能够让当前排列变大,从而得到下一个排列。
同时我们要让这个「较小数」尽量靠右,而「较大数」尽可能小。当交换完成后,「较大数」右边的数需要按照升序重新排列。这样可以在保证新排列大于原来排列的情况下,使变大的幅度尽可能小。
1)从末端开始遍历,寻找非降序的元素,记录下标
2)从末端开始,找到第一个大于上面元素的元素下标
3)交换数值,并且对后续的排列逆序
算法代码如下:
class Solution {
public:
void nextPermutation(vector<int>& nums) {
int right=nums.size()-1,front,i=right,end;
for(;i>=1;i--)
if(nums[i]>nums[i-1])
{front=i-1;break;} //找到非降序元素
if(front==right) //纯增序
reverse(nums.begin(),nums.end());
else
{
if(front<0) //纯降序
{
front=right-1;
end=right;
}
else
{
for(i=right;i>=front;i--)
if(nums[i]>nums[front])
{end=i;break;} //找到首个大于降序元素的元素下标
}
swap(nums[front],nums[end]);
for(i=front+1;i<right;i++,right--)
{
swap(nums[i],nums[right]);
}
}
}
};