求解的是下一个字典序,下面给出两个不同理解方式的字典序的定义:可以直接看第二种定义,但是算法还是用官方的定义来求解。
1)官方定义:字典序法是由当前序列直接生成下一个排列的算法:排列定义:P = P1P2```Pn
第一步:求满足关系式P(k-1)<P(k)的k的最大值,设为i,即
i = max{k|P(k-1)<P(k)}
第二步:求满足关系式P(i-1)<P(k)的k的最大值,设为j,即
j = max{k|P(i-1)<P(k)}
第三步:P(i-1)与P(j)互换。
第四步:把序列中P(i)P(i+1)```P(n)顺序逆转。
举例:对于3421,可知i = 2,j = 2 。P(1)与P(2)交换得4321,再将321逆转可得下一个排列4123
2)理解式的定义:以上面为例,3421,后三位421已经是完全逆序的,因此以3开头的已经全部结束,接下来是以4开头的,并且后三位是顺序的,因此事4123.再说一个例子,4312,后两位是顺序的,下一个字典序应把两个转为逆序即可。对2341来说,后两位是逆序的,说明以23开头的结束了,接下来是以24开头的,且后面是顺序的。
下面是1234的所有字典序,多看一下前后关系会明白的。
1234->1243->1324->1342->1423->1432->2134->2143->2314->2341->2413->2431->3124->3142->3214->3241->3412->3421->4123->4132->4213->4231->4312->4321
下面是代码:
class Solution { public: void swaptwoiterator(vector<int>::iterator begin,vector<int>::iterator end) {//交换两个迭代器指向的值,要自己写 int temp = *begin; *begin = *end; *end = temp; } void reverse(vector<int>::iterator begin,vector<int>::iterator end) {//反转区间上的值 size_t len = end - begin; for(size_t i = 0;i<len/2;i++) swaptwoiterator(begin+i,end-i-1); } void nextPermutation(vector<int> &num) { size_t len = num.size(); if(len<=1) return; size_t i = len - 1; while(i>0)//找到i的位置 { if(num[i-1]<num[i]) break; i--; } if(i == 0)//已经完全逆序,反转后输出 { reverse(num.begin(),num.end()); return; } size_t j = len - 1; while(num[j]<=num[i-1])//找到j的位置 j--; swap(num[i-1],num[j]); reverse(num.begin()+i,num.end()); } };