Next Permutation
Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers.
If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order).
The replacement must be in-place, do not allocate extra memory.
Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column.
1,2,3
→ 1,3,2
3,2,1
→ 1,2,3
1,1,5
→ 1,5,1
在组合数学中。求一个数列的全排列的方法有很多种,根据“字典序”生成全排列是较为常见的一种。同时C++ stl 中有现成的函数:next_permutation()
什么是字典序?
对于数字1、2、3......n的排列,不同排列的先后关系是从左到右逐个比较对应的数字的先后来决定的。 例如对于5个数字的排列 12354和12345,排列12345在前,排列12354在后。按照这样的规定,5个数字的所有的排列中最前面的是12345,最后面的是 54321。
求根据字典序求下一个序列算法:
设P是1~n的一个全排列:p=p1p2......pn=p1p2......pj-1pjpj+1......pk-1pkpk+1......pn
1)从排列的右端开始,找出第一个比右边数字小的数字的序号j(j从左端开始计算),即 j=max{i|pi<pi+1}
2)在pj的右边的数字中,找出所有比pj大的数中最小的数字pk (注意:此处pk应该从最右边开始找起,如果相等则优先靠右的值)
3)对换pj,pk
4)再将pj+1...pk-1pkpk+1pn倒转得到排列p'=p1p2....pj-1pjpn.....pk+1pkpk-1.....pj+1,这就是排列p的下一个排列。
例如:14532是数字1~5的一个排列。从它生成下一个排列的步骤如下:
自右至左找出排列中第一个比右边数字小的数字4 14532
在该数字后的数字中找出比4大的数中最小的一个5 14532
将5与4交换 15432
将432倒转 15234
所以14532的下一个全排列为15432
在该数字后的数字中找出比4大的数中最小的一个5 14532
将5与4交换 15432
将432倒转 15234
所以14532的下一个全排列为15432
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
class Solution{
public:
void nextPermutation(vector<int> &num) {
int len=num.size();
if(len<=1)return;
//(1)从右端开始,找出第一个比右边数小的数据序号j
int j;
for(j=len-2;j>=0;--j){
if(num[j]<num[j+1])
break;
}
if(j==-1){ //表示num为全排列的最大值,下一个则为逆序,最小值。
reverse(num.begin(),num.end());
return;
}
//(2)在pj的右边的数字中,(从右向左)找出所有比pj大的数中最小的数字pk
int k=j+1;
for(int i=len-1;i>j;--i){
if(num[i]>num[j]){ //从右至左遇到第一个比num[j]大的就是所求Pk
k=i;
break;
}
}
//(3)对换pj,pk
swap(num[j],num[k]);
//(4) 再将pj+1...pk-1pkpk+1pn倒转得到排列p'=p1p2....pj-1pjpn.....pk+1pkpk-1.....pj+1,这就是排列p的下一个排列。
reverse(num.begin()+j+1,num.end());
}
};