求字典序的直观方法就是从后往前不断操作,让一个串越来越大,next_permutation中给出了求字典序的方法,这个方法是:
1、如果串是完全逆序的,它不能再大了(但仍把它反转,使其成为最小串)。2、如果串没有完全逆序,它就还能变大,怎么变大呢?如果最后两个元素是顺序的,把它们逆序这个串就变大了;如果最后两个元素是逆序的,那么串的尾部就有一个逆序子串,把这个逆序子串做某操作就可以。什么是“某操作”呢?
因为子串是逆序的,从后往前它会变得越来越大的,这样子串很高兴,但既然整个串不是完全逆序,那从后往前子串就会遇到一个小的数x,这样就不能再继续变大了。子串很生气,它要教训x,因为x是个小数,逆序列中就有一个成员可以和x交换同时保证整个子列仍是逆序的,这个成员就是子列中第一个比x大的数y,这样y强迫x与它交换位置。交换之后我们看整个串一定是变大了,因为x位置的那个数变大了。交换之后子串很高兴,它翻了个身,变成顺序的了。既然变成顺序的,那光看子串的话,子串一定是变小了,同时整个串变大了(变大的幅度尽量小,在子串大的过x的成员中,y就最小)。这就是“某操作”。
这样我们写一个next_permutation
void nextPermutation(vector<int> &v){
if(v.size()<=1)return ;
//more than two numbers
int i,j,k;
for(i=v.size()-1; i>=0;--i)
if(v[i]>v[i-1]) break;
//if(i==0) v is sorted already
if(i==0){
reverse(v.begin(),v.end());
return; }
// v is not sorted,
for(j=v.size()-1; j>=i; --j)
if(v[j]>v[i-1]) break;
swap(v[i-1],v[j]);
reverse(v.begin()+i,v.end());
}