zoukankan      html  css  js  c++  java
  • 字典序全排列

    给出正整数n,则1~n这n个数可以构成n!种排列,把这些排列按照从小到大的顺序(字典顺序)列出,如n=3时,列出1 2 3,1 3 2,2 1 3,2 3 1,3 1 2,3 2 1 这6个排列。 

    字典序算法如下:

    假设这n个数的某一个排列为 P: P1 P2 P3...Pj-1 Pj Pj+1...Pk-1 Pk Pk+1...Pn

    1.从该序列的最右端开始向左找出第一个比与自己相邻的右边数小的数,记其下标为j,即j = max{i|Pi<pi+1}.

    2.找出Pj右边比Pj大的最小数Pk.

    3.交换Pj,Pk.此时序列变为 P’: P1 P2 P3...Pj-1 Pk Pj+1...Pk-1 PPk+1...Pn

    4.将Pj+1...Pn 倒转,即得到此序列的后一个序列 P”: P1 P2 P3...Pj-1 Pn...Pk+1 PPk-1...Pj+1

    例:

    1 2 3 5 7 4 6 10 9 8为1-10的一个排列

    1.从该序列的最右端开始向左找出第一个比与自己相邻的右边数小的数6,其下标为7

    2.6右边比6大的最小数为8

    3.交换6,8得到1 2 3 5 7 4 8 10 9 6

    4.将P8-P10倒转得到:1 2 3 5 7 4 8 6 9 10即为下一个序列

    代码实现:

     1 //对1-n的某个已知排列求按字典序其后的第s个排列
     2 #include<cstdio>
     3 #include<algorithm>
     4 using namespace std;
     5 const int N = 1030;
     6 //将数组下标a-b的元素翻转
     7 void Flip(int n[],int a,int b){
     8  for(int i = a,j = b; i < j; i ++, j --){
     9      swap(n[i],n[j]);
    10  }
    11 }
    12 //求第k个排列
    13 void order(int n,int a[],int s){
    14      int j,k,min,flag;
    15  while(s --){
    16     min = n+1;
    17    flag = 1;
    18    for(int i = n-1; i >= 1; i --){
    19      if(a[i] < a[i+1]){
    20           flag = 0;
    21           j = i;
    22           break;
    23      }
    24    }
    25    if(flag){
    26      for(int i = 1; i <= n; i ++){//排列为n n-1...2 1
    27           a[i] = i;
    28      }
    29    }
    30    else{
    31      for(int i = j+1; i <= n; i ++){
    32           if(a[i] > a[j]){
    33                if(a[i] < min){
    34                     min = a[i];
    35                     k = i;
    36                }
    37 
    38           }
    39       }
    40       swap(a[j],a[k]);
    41       Flip(a,j+1,n);
    42    }
    43   }
    44 }
    45 int main(){
    46    int m,n,k,num[N];;
    47    scanf("%d",&m);
    48    while(m --){
    49      scanf("%d%d",&n,&k);
    50      for(int i = 1; i <= n; i ++){
    51           scanf("%d",&num[i]);
    52      }
    53      order(n,num,k);
    54      for(int i = 1; i <= n; i ++){
    55           printf(i == 1?"%d":" %d",num[i]);
    56      }
    57      printf("
    ");
    58    }
    59 return 0;
    60 }

    另外表示可以用c++ STL中的next_permutation函数生成全排列。。

    链接:http://www.cnblogs.com/TonyNeal/archive/2013/05/11/next_permutation.html

    Keep It Simple and Stupid.
  • 相关阅读:
    aircrack-ng 多网卡启动后环境清理
    Docker create image
    预加载(学习一)
    activity+fragment多次切换出现页面空白问题
    万能的Volley
    关于下拉刷新你是否真的非常理解还是只会搬砖?附 Android 实例子源代码文件下载地址380个合集
    如何将Java源代码文件的编码从GBK转为UTF-8?
    如何操作笔记本显得逼格很高?
    跑马灯源代码
    关于java、Android中Math的一些用法
  • 原文地址:https://www.cnblogs.com/FleetingTime/p/3728711.html
Copyright © 2011-2022 走看看