求字典序的下一个排列(对应lc的Next Permutation)

时间:2021-10-01 23:20:29

如果字典序的下一个排列不存在,则返回升序排序。

步骤如下:

(1)找到排列中最后(最右)一个升序的首位位置i,x = ai。

(2)找到排列中第i位右面比ai大的最右位置j,y = aj。

(3)交换x和y。

(4)把第i+1到数组最后一位的部分旋转。

经过以上4个步骤即可得到下一个排列。

比如当前序列为51432,算法的执行过程为

(1)i = 1,x = 1 。

(2)j = 4,y = 2 。

(3)交换x和y后,得到52431 。

(4)431部分旋转,得到52134 。

下面过程是从组合数学中总结的,说的也是一个意思:

(1) 求满足关系式pj-1<pj的j的最大值,设为i,即
       I=max{ j | pj-1<pj }
(2) 求满足关系式pj-1<pk的k的最大值,记为h
(3) 交换pj-1和ph的值
(4) 从pj开始进行逆序排列


代码中的Qsort函数(快排)其实只用以旋转函数就行。

class Solution {
public:
void nextPermutation(vector<int>& nums) {
if(nums.size()<=1)
return ;
if(isDescending(nums)){
sort(nums.begin(), nums.end());
return ;
}
int j=1, i=0;
for( ; i<nums.size(); ++i){
if(nums[i] > nums[i-1])
j=i;
}
int h=j;
for(i=j; i<nums.size(); ++i) {
if(nums[i] > nums[j-1])
h=i;
}
swap(nums[j-1], nums[h]);
int low=j, high=nums.size()-1;
Qsort(nums, low, high);
}
private:
void Qsort(vector<int> &nums, int low1, int high1) {
if(low1 >= high1)
return ;
int low=low1, high=high1;
int key=nums[low];
while(low < high) {
while(low<high && nums[high]>=key)
--high;
nums[low]=nums[high];
while(low<high && nums[low]<=key)
++low;
nums[high]=nums[low];

}
nums[low]=key;
Qsort(nums, low1, low-1);
Qsort(nums, low+1, high1);
}
bool isDescending(vector<int> &nums) {
int i=0;
for(i=1; i<nums.size(); ++i) {
if(nums[i] > nums[i-1])
return false;
}
return true;
}
};