(7.15)康托展开,就是把全排列转化为唯一对应自然数的算法。它可以建立1 ~ n的全排列与[1, n!]之间的自然数的双向映射。
1、康托展开:
尽管我并不清楚康托展开的原理何在,这个算法的过程还是比较好记的。正确性之后有机会询问下学长。
如果从1开始给全排列的排名从大到小编号的话(从0开始也可,建立的是与[0, n!-1]的映射,本质相同),定义rk为排名,a是排列数组,排列有n位(最低位是第0位),那么有公式
rk - 1 = cnt[n-1] * (n-1)! + cnt[n-2] * (n-2)! + ... + cnt[0] * 0!
其中cnt数组的含义是未统计的数字中,小于a[i]的数字有多少个。
举例:计算排列3 4 2 1对于{1, 2, 3, 4}的排名
首先取出最高位(第三位),小于数字3的数有两个,所以cnt[3] = 2,rk += 2 * 3!,rk = 12。
然后取出4,小于4的数有三个,但是3已经被统计过了,所以cnt[2] = 2,rk += 2 * 2!,rk = 16.
取出2,小于2的只有1,cnt[1] = 1,rk += 1 * 1!,rk = 17。
最后由于除第0位本身外已经没有数了,cnt[0]恒等于0。所以3 4 2 1的排名为18。
代码:
- //阶乘