简要介绍康托展开

本篇文章并不会详细讲解康托展开的数学原理,有兴趣的朋友可以另行寻找。

康托展开

作用:判断这个数在其各个数字全排列中从小到大排第几位。比如 132,在1、2、3的全排列中排第2位。


首先定义一个特殊的进制:0! 1! 2! 3! 4! ...

即——1 1 2 6 24 ...

把它保存到一个数组里: = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880}

可类比其他进制,如十进制:

1 10 100 1000 ...

则312=(3*100 + 1*10 + 2*1)

某个排列的位置算法: ∑(比这位上的数(从最高位开始)小的数的个数 * FAC[ 这位数在排列中从右到左的位数 ]) + 1 例子:

2431 = (1*6 + 2*2 + 1*1 + 0*1) + 1 = 12

312 = (2*2 + 0*1 + 1*1) +1 = 5

312的验证:

①123

②132

③213

④231

⑤312

⑥321

 

代码:

//阶乘0!~n!的数组,此处n=9
 static const int FAC[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880};
 ​
 /*
     康托展开
     参数:存放某个全排列的num[]数组,如:num[]={3,1,2};全排列数字的个数,像前面         的312的n就等于3
     返回值:返回这个已知全排列在全排列中的位置名次
 */
 int KT(int num[],int n)
 {
     int ans=1,temp; //temp为暂存前面比当前位小的个数
     for(int i=0;i<n;i++)
     {
         if(i==0)
         {
             ans=ans+(num[i]-1)*FAC[n-1];
         }
         else
         {
             temp=num[i]-1;
             for(int j=0;j<i;j++)
             {
                 if(num[j]<num[i])
                     temp--;
             }
             ans=ans+temp*FAC[n-1-i];
         }
     }
     return ans;
 } 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值