思路
我们观察以下序列
123456
123465
123546
123564
123654
…
可以看出这是个紧凑变化的排列,题目求解大意也是如此。
如何根据已有序列求出下一个排列呢?
观察可知,我们需要将排在前面较小的数nums[j]与排在后面较大的数字nums[k]交换,j<k,比如说123465,我们交换的是4和5,而这样子选择有什么要求呢?
1.我们希望较大数字的位置k尽可能地靠右,然后较小数字的位置j尽可能靠近k,这样保证变化幅度变化是最小的。
3.在交换完之后,因为需要改变k后面的序列,让其尽可能小,这样保证了变化幅度最小。
实现
1.从后向前扫描,找到第一个逆序对(j,j+1)。
2.从后向前扫描,找到第一个小于nums[j]的数nums[k],容易证明k>j。
3.交换nums[j]和nums[j],然后j后面的序列按升序排列即可获得大于当前值的最小值了。
代码
class Solution {
public:
void nextPermutation(vector<int>& nums) {
int j=nums.size()-2;
while(j>=0)
{
if(nums[j]<nums[j+1])
break;
j--;
}
int k=nums.size()-1;
while(k>j&&j>=0)
{
if(nums[k]>nums[j])
{
break;
}
k--;
}
if(j>=0)
{
swap(nums[j],nums[k]);
}
sort(nums.begin()+j+1,nums.end());
}
};