#include <iostream> #include <algorithm> #include <cstring> using namespace std; int main() { for(string s;cin>>s;) { if(s.empty()) continue; if(s.length()<=1) cout<<"No more permuntion"<<endl; //ele_left右边最大减序子集左边相邻的一个元素 string::iterator ele_left=s.end(),ele_right; for(--ele_left;ele_left!=s.begin();--ele_left)//查找右边最大的减序子集 if(*(ele_left-1)<*ele_left) break; if(ele_left==s.begin()) cout<<"No more permuntion"<<endl; ele_left--; for(ele_right=ele_left+1;ele_right!=s.end();++ele_right) if(*ele_right<*ele_left) break; //交换iPivot和iNewHead的值,但不改变它们的指向 iter_swap(ele_left,--ele_right); reverse(ele_left+1,s.end());//反转右侧减序子集,使之成为最小的增序子集 cout<<s<<endl; } return 0; }
next_permutation函数将按字母表顺序生成给定序列的下一个较大的排列,直到整个序列为降序为止。prev_permutation函数与之相反,是生成给定序列的上一个较小的排列。
二者原理相同,仅遍例顺序相反,这里仅以next_permutation为例介绍算法。
先对序列大小的比较做出定义:两个长度相同的序列,从两者的第一个元素开始向后寻找,直到出现一个不同元素(也可能就是第它们的第一个元素)
该元素较大的序列为大,反之序列为小;若一直到最后一个元素都相同,那么两个序列相等。
复杂度
最好的情况为pn的最后的2个元素构成一个最小的增序子集,交换次数为1,复杂度为O(1),最差的情况为1个元素最小,而后面的所有元素构成减序子集,这样需要先将第1个元素换到最后,
然后反转后面的所有元素。交换次数为1+(n-1)/2,复杂度为O(n)。这样平均复杂度即为O(n/2)。
参考链接:https://jingyan.baidu.com/article/63acb44a90370061fcc17e18.html?qq-pf-to=pcqq.c2c