• 用康托展开实现全排列(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 中国大陆许可协议进行许可。
  • 相关阅读:
    在matlab中出现警告 Function call XX invokes inexact match
    VC2008调用matlab生成的dll和lib
    关于mwArray 的一些资料(一)
    关于C#中的3个timer类(申明是转贴的哦)
    C#教程 PDF
    我也做他个vote machine
    如何用UltraEdit编译C#源程序(再次申明这也是转贴的哦!)
    C#使用技巧调用DLL(还是转贴哦!)
    线程池
    Java web开发中如何自动生成文章html页面
  • 原文地址:https://www.cnblogs.com/MrLJC/p/3366278.html
Copyright © 2020-2023  润新知