Question31–Next Permutation
对于一个给定的整数序列,输出它的下一个字典顺序的序列。若给出的序列已经最大,则输出最小序列。
eg:5,4,3 –>3,4,5
1,2,3 –>1,3,2 –>2,1,3 –>2,3,1 –>3,1,2 –> 3,2,1
method 1
记该序列为a,假设该序列共有n位,我们从后往前看,i(从n-1到1)
很容易知道,要得到比目前序列大一点的下一个序列,必定是把一个高位的小数字和它后面比它大的数字中的最小的换过来,然后再把后面的数字按升序排列。
我们可以从后向前遍历,然后一直在原序列的后面遍历过的空间维持一个升序小序列记为h,初始h只包含a[n]。
- 若a[i]小于h序列中的第一个元素即a[i+1],则将a[i]和a[i+1]交换,得到结果。
- 若a[i]大于或等于a[i+1],并大于或等于h中最后一个元素a[n],则将h逐位前移,将a[i]符给a[n]。
- 若a[i]大于或等于a[i+1],且小于h中最后一个元素a[n],则扫描h找到第一个大于a[i]的元素,并互换位置,得到结果。
code
void nextPermutation(vector<int>& nums){
int numsize=nums.size();
for(int i=numsize-2; i>-1; i--){
if(nums.at(i)<nums.at(i+1)){
int temp=nums.at(i);
nums[i]=nums[i+1];
nums[i+1]=temp;
return;
}
else{
int key=nums[i];
if(key>=nums.back()){
for(int j=i+1; j<numsize; j++){
nums[j-1]=nums[j];
}
nums[numsize-1]=key;
}
else{
for(int j=i+1; j<numsize; j++){
if(key<nums[j]){
nums[i]=nums[j];
nums[j]=key;
return;
}
}
}
}
}
}
method 2
- 从后面往前面遍历,依次比较相邻两个元素,直到找到第一个前面的元素大于它相邻的后面的元素时停止。
- 然后继续从后向前遍历刚刚那个元素后面的序列,直到找到第一个比该元素大的元素停止,交换这两个元素。
- 然后,将那个元素后面的序列倒过来,即按升序排列。
code
void nextPermutation(vector<int>& nums){
int numsize=nums.size();
int i=numsize-2;
while(i>=0&&nums[i]>=nums[i+1]) i--;
if(i>=0){
for(int j=numsize-1; j>=i+1; j--){
if(nums[j]>nums[i]){
int temp=nums[i];
nums[i]=nums[j];
nums[j]=temp;
break;
}
}
}
int p=i+1, q=numsize-1;
while(p<q){
int temp=nums[p];
nums[p]=nums[q];
nums[q]=temp;
p++;
q--;
}
}