本篇文章并不会详细讲解康托展开的数学原理,有兴趣的朋友可以另行寻找。
康托展开
作用:判断这个数在其各个数字全排列中从小到大排第几位。比如 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;
}