蓝桥杯

来源:互联网 发布:心理健康测试软件 编辑:程序博客网 时间:2024/06/05 18:19
下一个排列

先看看网上是怎么介绍next_permutation函数:

   next_permutation函数在 组合数学中经常用到排列,这里介绍一个计算序列全排列的函数:next_permutation(start,end),和prev_permutation(start,end)。这两个函数作用是一样的,区别就在于前者求的是当前排列的下一个排列,后一个求的是当前排列的上一个排列。至于这里的“前一个”和“后一个”,我们可以把它理解为序列的字典序的前后,严格来讲,就是对于当前序列pn,他的下一个序列pn+1满足:不存在另外的序列pm,使pn<pm<pn+1.


分析:
在做一道“困难的串”的算法题时候发现c语言没有类似c++ next_permutation函数可以调用, 网上找了一下关于c语言写next_permutation函数也比较乱,于是自己写了一下。

对于一个序列(数字,如果要换成字母就65 +或 97 +并用%c输出)从倒序寻找数字当A[n]>A[n-1]时,然后寻找A[n](包括A[n])到最后面的最小值min。将min与A[n-1]交换。余下的数字(指的是A[n]到最后面的数,包括A[n])按从小到大排序即可。

比如:1 5 4 3 2  ,这序列计算下来A[n-1](1),则A[n](5)后面的最小min(2)(注意这个最小的数要大于A[n-1]至于为什么就想一下)。将min(2)与A[n-1](1)交换。剩下的A[n-1](交换后变成2)后面排序得 2 (1 3 4 5 )

代码在此:
#include<stdio.h>void swap (int *a, int *b) {//交换函数 int temp;temp = *a;*a = *b;*b = temp;}void sort (int a[], int st, int fi) {//自己写的选择排序替代c++ sort();当然肯定没c++的sort()效率高 ;对a[]数组的下标st到下标fi的排序 int i, j, k, temp;int n = fi + 1;for(i = st; i < n-1; i ++){k = i;for(j = i+1; j < n; j ++){if(a[k] > a[j])k = j;}if(k != i){temp = a[k];a[k] = a[i];a[i] = temp;}}}int Next_Permutation (int A[], int n) {int i;int num;//待交换的数的下标 for(i = n - 2; i >= 0; i --){//计算出A[n-1] < [n]的情况,A[n-1]待交换数中的n-1就是num if (A[i+1] > A[i]) break;}if(i < 0)//说明数列已经是降序数列 如 3 2 1 没有 3 位的后续排列 return 0;num = i;//待交换的数 i = i + 1;//i做为 A[n] 的下标 int min = i;//先默认 A[n] 为最小数 i ++;// i++寻找A[n-1]右边更小的数 for(; i < n; i ++){if(A[i] < A[min] && A[i] >= A[num]){// && A[i] >= A[num]这个条件必须加,因为这是个定序推导,不然你去掉试一试min = i;}}swap(A + num, A + min);//交换 sort(A, num + 1, n - 1);// A[n-1]之后的重排 return 1;}int main () {int i;int n;//int a[] = {65, 66, 67, 68};//大写之母 int a[] = {1, 2, 3, };n = 3;for(i = 0; i < n; i ++)printf("%d ", a[i]);printf("\n");while(Next_Permutation(a, n)){for(i = 0; i < n; i ++)printf("%d ", a[i]);printf("\n");}return 0; }


0 0
原创粉丝点击