zoukankan      html  css  js  c++  java
  • 康托展开及其逆运算

    一、定义

    X=an*(n-1)!+an-1*(n-2)!+...+ai*(i-1)!+...+a2*1!+a1*0!

    ai为整数,并且0<=ai<i(1<=i<=n)

    简单点说就是,判断这个数在其各个数字全排列中从小到大排第几位。

    比如 132,在1、2、3的全排列中排第2位。

     二、作用

    维基:n位(0~n-1)全排列后,其康托展开唯一且最大约为n!,因此可以由更小的空间来储存这些排列。由公式可将X逆推出对应的全排列。

    它可以应用于哈希表中空间压缩,

    而且在搜索某些类型题时,将VIS数组量压缩。

    三、康托展开求法

    比如2143 这个数,求其展开:

    从头判断,至尾结束,

    ① 比 2(第一位数)小的数有多少个->1个就是1,1*3!

    ② 比 1(第二位数)小的数有多少个->0个0*2!

    ③ 比 4(第三位数)小的数有多少个->3个就是1,2,3,但是1,2之前已经出现,所以是  1*1!

    将所有乘积相加=7

    比该数小的数有7个,所以该数排第8的位置。

    1234  1243  1324  1342  1423  1432
    2134  2143  2314  2341  2413  2431
    3124  3142  3214  3241  3412  3421
    4123  4132  4213  4231  4312  4321

     四、代码

    int  fac[] = {1,1,2,6,24,120,720,5040,40320}; //i的阶乘为fac[i]  
    // 康托展开-> 表示数字a是 a的全排列中从小到大排,排第几  
    // n表示1~n个数  a数组表示数字。  
    int kangtuo(int n,char a[])  
    {  
        int i,j,t,sum;  
        sum=0;  
        for( i=0; i<n ;++i)  
        {  
            t=0;  
            for(j=i+1;j<n;++j)  
                if( a[i]>a[j] )  
                    ++t;  
            sum+=t*fac[n-i-1];  
        }  
        return sum+1;  
    }  

    五、康托展开的逆:

    康托展开是一个全排列到自然数的双射,可以作为哈希函数。

    所以当然也可以求逆运算了。

    逆运算的方法:

    假设求4位数中第19个位置的数字。

    ① 19减去1  → 18

    ② 18 对3!作除法 → 得3余0

    ③  0对2!作除法 → 得0余0

    ④  0对1!作除法 → 得0余0

    据上面的可知:

    我们第一位数(最左面的数),比第一位数小的数有3个,显然 第一位数为→ 4

    比第二位数小的数字有0个,所以 第二位数为→1

    比第三位数小的数字有0个,因为1已经用过,所以第三位数为→2

    第四位数剩下 3

    该数字为  4123  (正解)

    用代码实现上述步骤为:

    int  fac[] = {1,1,2,6,24,120,720,5040,40320};  
    //康托展开的逆运算,{1...n}的全排列,中的第k个数为s[]  
    void reverse_kangtuo(int n,int k,char s[])  
    {  
        int i, j, t, vst[8]={0};  
        --k;  
        for (i=0; i<n; i++)  
        {  
            t = k/fac[n-i-1];  
            for (j=1; j<=n; j++)  
                if (!vst[j])  
                {  
                    if (t == 0) break;  
                    --t;  
                }  
            s[i] = '0'+j;  
            vst[j] = 1;  
            k %= fac[n-i-1];  
        }  
    } 
  • 相关阅读:
    初窥AndroidPlot(一)
    Android Studio安装、配置
    Android SDK Android NDK Android Studio 官方下载地址及方式
    学习Android图表绘制
    ActionBar研究(二)
    获取Android版本信息和程序版本号
    Android手机获取通话记录和短信记录
    Android开发之监听或获取手机短信内容【转】
    android 几种发送短信的方法【转】
    android开源框架android-async-http
  • 原文地址:https://www.cnblogs.com/aiguona/p/9146729.html
Copyright © 2011-2022 走看看