字符串和数字的映射 康托展开
康托展开就是把一个字符串映射成一个数字
康托展开的公式是 X=an*(n-1)!+an-1*(n-2)!+...+ai*(i-1)!+...+a2*1!+a1*0! 其中,ai为当前未出现的元素中是排在第几个(从0开始)。
注意是从0开始的,理解的话,先ABCD A在ABCD里是第0个所以a4=0,接着把A去掉,B在BCD里面是第0个所以a3=0,接着把B去掉,依次都为0
1 int fac[] = {1,1,2,6,24,120,720,5040,40320,362880};// factorial阶乘 2 //康托展开 3 int cantor(char arr[]) 4 { 5 int res = 0; 6 bool vis[10] = {0}; 7 for(int i = 0 ; i < 9; i++) 8 { 9 int x = s[i] -'0', y = 0; 10 for(int j = 1; j < x; j++)//这步的实质就是找x在序列中是第几大 11 //如果前面出现过比x大的数,那个数一定比x大所以扫不到,如果前面出现比它小的数,那个数已经被标记为1了 12 if(!vis[j]) 13 y++; 14 res += y*fac[8-i]; 15 vis[x] = true; 16 } 17 return res; 18 }
康托逆展,用辗转相除法实现,先把康托展示的值除n-1!,除数为an,余数继续执行
通过康托逆展开生成全排列
如果已知 s = ["A", "B", "C", "D"],X(s1) = 20,能否推出 s1 = ["D", "B", "A", "C"] 呢?
因为已知 X(s1) = a4*3! + a3*2! + a2*1! + a1*0! = 20,所以问题变成由 20 能否唯一地映射出一组 a4、a3、a2、a1?如果不考虑 ai 的取值范围,有
3*3! + 1*2! + 0*1! + 0*0! = 20
2*3! + 4*2! + 0*1! + 0*0! = 20
1*3! + 7*2! + 0*1! + 0*0! = 20
0*3! + 10*2! + 0*1! + 0*0! = 20
0*3! + 0*2! + 20*1! + 0*0! = 20
等等。但是满足 0 <= ai <= n-1 的只有第一组。可以使用辗转相除的方法得到 ai,如下图所示:
浙公网安备 33010602011771号