康托展开

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了康托展开相关的知识,希望对你有一定的参考价值。

康托展开:求一组数在全排列中第几小

例如:{1 ,2, 3, 4, 5, 6} 求 135264 在全排列中的第几小?

时间复杂度:

康托展开 O(n)

原理: 康托展开的公式是 X=an*(n-1)!+an-1*(n-2)!+...+ai*(i-1)!+...+a2*1!+a1*0! 其中,ai为当前未出现的元素中是排在第几个(从0开始)。

1是当前未出现的数字中最小(第0小)所以 0*5! 因为1排在第一个位置 后面有5个数 所以是5!

3是当前未出现的数字中第一小 所以1*4!

5是当前未出现的数字中第二小 所以2*3!

下面依次类推

X=0*5! + 1*4! + 2*3! + 0*2! + 1*1! + 0 =37

也就是说 135264 在全排列中 它的前面还有37个比它小的数字

所以 它是第38小的数字。

sizeof(s)/sizeof(*s) s为数组名 这个式子是求数组的长度。

代码:

 1 #include <cstdio>
 2 
 3 const int fac[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320};//阶乘
 4 
 5 int KT(int a[],int n)
 6 {
 7     int i, j, cnt, sum;
 8     sum = 0;
 9     for(i=0;i<n;i++)
10     {
11         cnt = 0;
12         for(j=i+1;j<n;j++)
13         {
14             if(a[i]>a[j]) cnt++;
15         }
16         sum = sum + cnt * fac[n-i-1]; 
17     }
18     return sum;
19 }
20 
21 int main()
22 {
23     int s[] = {1,3,5,2,6,4};
24     int re;
25     re = KT(s,sizeof(s)/sizeof(*s));
26     printf("%d",re+1);
27     return 0;
28 }

 

以上是关于康托展开的主要内容,如果未能解决你的问题,请参考以下文章

全排列的编码与解码——康托展开 (附完整代码)

康托展开 / 逆康托展开

康托展开 & 逆康托展开

康托展开小结-

LG5367 「模板」康托展开 康托展开

[学习][Math]康托展开和逆康托展开