字典序的下一个排列

来源:互联网 发布:php打印空格 编辑:程序博客网 时间:2024/05/17 03:50

先上模板

//数组a的下一个字典序排列。stl貌似会超时。手写还是快#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int a[1025];void next(int N){    int index = 0;    bool flag = false;    for(int i = N - 2 ; i >= 0 ; i--){        if(a[i] < a[i + 1]){//找第一个小于后一个数的数字            flag = true;            index = i;            break;        }    }    if(flag == flase){//这个序列已经是递减的排列,下一个肯定是递增的        sort(a ,a + N);        return;    }    int temp = index + 1;    //如果后面已经是递减了,那么就找到位于现在制定的两个数中间那个数换上来,并将后面按小到大排序      //例如1 2 4 3,假设现在index指向2,则temp指向4,i指向了3,因为3<4&&3>2所以将3与2交换,后面的按小到大排序      //因为这么做的前提是2后面是递减的,所以我们只要从最后找到一个最先位于index和tem之间的值即可,如此循环      for(int i = N - 1 ; i >= index + 2 ; i--){        if(a[i] < a[temp] && a[i] > a[index]){            temp = i;            break;        }    }    int change = a[index];    a[index] = a[temp];    a[temp] = change;    sort(a + index + 1 , a + N);}

今天做了个poj1011,这是个组合数学的一个算法。今天学了一发,受教了。还查了一发证明,不仅感叹。。。牛逼。最近学离散的集合论,始终不知道是干啥的。。。好尴尬,虽然说,模板和证明都不是我自己的,但是!!!合起来就是我的。原创!
那个条件很烦直接上例子

例子更能说明:

假设输入为 5 5 2 4 7 6 3

从后往前观察,对于A[5] = 6 >= A[6] = 3。(交换A[5]和A[6]得到的排列: 5 5 2 4 7 3 6 小于原排列,这一步是没有必要做的,只是为了让大家看清楚)

A[4] = 7 >= A[5] >= A[6]。(交换A[4]和A[5]或者A[4]和A[6]等,得到的都比原排列小)

A[3] = 4 < A[4] >= A[5] >= A[6],这时从7 6 3中选择6,6是这三个数中大于4的最小的数,交换A[3] = 4和A[5] = 6,得到: 5 5 2 6 7 4 3

明显5 5 2 6 7 4 3比原排列大,但不是原排列的next permutation。

需要调整7 4 3得到最小的3 4 7,最终就是输出5 5 2 4 3 6 7
!!!!!!!!!!!!!!!!!!!!证明!!!!!!!!!!!!!!
这里写链接内容
证明写的极其帮!

0 0
原创粉丝点击