zoukankan      html  css  js  c++  java
  • 用康托展开实现全排列(STL、itertools)

    康拓展开:

    $X=a_n*(n-1)!+a_{n-1}*(n-2)!+ldots +a_2*1!+a_1*0!$

          X=an*(n-1)!+an-1*(n-2)!+...+ai*(i-1)!+...+a2*1!+a1*0! 其中,a为整数,并且0<=ai<i(1<=i<=n)

    这个式子就是康托展开,初看同排列没什么关系,实则不然。下面通过举个例子看一下

    一、用康托展开判断一个排列是第几小的

    以{1,2,3}为例。我们定义排列的顺序从小到大为123,132,213,231,312,321。

    然后我们随便给一个比如312,要判断他在排列中第几大的,则我们可以这样思考,首先第一个比3小可以是1或2,则有2*2!中,第二位比1小,没有,第三位没有。如果说这个不够明显我们看一下321是第几个,首先比3小的2*2!,比2小的1*1!,共2*2!+1*1!=6,。至于其他的各位有兴趣也可以去计算。但这不是我们的重点,我们的重点是得到全排列。

    二、康托逆展开

    既然康托展开可以判断出某个组合是第几个,那么他是不是也可以构造出第几个排列的值呢?答案是可以的,这里我们叫做康托逆展开。同样的举个例子来看他的工作过程。还是{1,2,3}。现在我们要求出第四大的排列,首先(4-1)%2!=1余1,这个结果表示有有1个数比他小的是2,也就是排列的第一位是2,然后1-1=0则表示没有比第二个大的,即第二个为3,故231。其他例子各位可以自己试。这里给出C++的实现代码

     1 int fac[]={1,1,2,6,24,120,720,5040};
     2 int* cantor(int m,int n)//m is for the size of the set,n is the sequence number
     3 {
     4     bool flag[20]={false};
     5     int *ans=new int[20];
     6     int i=m;
     7     int j=n-1;
     8     while(i--)
     9     {
    10         int temp=(j)/fac[i]+1;
    11         int count=-1,t;
    12         for(t=0;t<m;t++)
    13         {
    14             if(!flag[t])
    15             count++;
    16             if(temp==count)
    17             break;
    18         }
    19         ans[m-i-1]=t;
    20         flag[t]=true;
    21         j=(j)%fac[i];
    22     }
    23     //for(int t=0;t<m;t++)
    24     //cout<<ans[t];
    25     //cout<<endl;
    26     return ans;
    27 }

    不过写完之后突然发现STL中有实现全排列的函数叫

    next_permutation()

    有兴趣可以看看

     --------------------------------------------------python-----------------------------------------------------------

    使用python的话也有一个相应的库iteltools,可以实现排列组合

    使用方法见代码

    1 >>>import itertools
    2 >>>list(itertools.permutations([1,2,3,4],4))
    3 [(1, 2, 3, 4), (1, 2, 4, 3), (1, 3, 2, 4), (1, 3, 4, 2), (1, 4, 2, 3), (1, 4, 3, 2), (2, 1, 3, 4), (2, 1, 4, 3), (2, 3, 1, 4), (2, 3, 4, 1), (2, 4, 1, 3), (2, 4, 3, 1), (3, 1, 2, 4), (3, 1, 4, 2), (3, 2, 1, 4), (3, 2, 4, 1), (3, 4, 1, 2), (3, 4, 2, 1), (4, 1, 2, 3), (4, 1, 3, 2), (4, 2, 1, 3), (4, 2, 3, 1), (4, 3, 1, 2), (4, 3, 2, 1)]
    4 >>>list(itertools.combinations([1,2,3,4],4))
    5 [(1, 2, 3, 4)]

    如果你觉得内容对你有帮助,请点个赞

    知识共享许可协议
    本作品采用知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议进行许可。
  • 相关阅读:
    今天面试一些程序员(新,老)手的体会
    UVA 10635 Prince and Princess
    poj 2240 Arbitrage
    poj 2253 Frogger
    poj 2485 Highways
    UVA 11258 String Partition
    UVA 11151 Longest Palindrome
    poj 1125 Stockbroker Grapevine
    poj 1789 Truck History
    poj 3259 Wormholes
  • 原文地址:https://www.cnblogs.com/MrLJC/p/3366278.html
Copyright © 2011-2022 走看看