康托展开和康托逆展开解决第K个排列问题
来源:互联网 发布:淘宝显示获取店铺失败 编辑:程序博客网 时间:2024/05/07 15:04
集合{1,2,3,…,n}包含了 n!种不同的排列,将这n!种排列从小到大进行排序,某个排列为第K 个, 求K时,使用康托展开,已知K求对应的排列时,使用康托逆展开。
康托展开
对于某个排列 a1, a2, a3, .. , an ,将其存入数组s{a1,a2,a3,…,an} 求它在n!个排列中的位置k,
用RLi表示ai后面比ai小的数的个数,Ri表示ai后面的数的个数,
k -1= RL1*R1! + RL2*R2!+…+RLn*Rn!(RLn和Rn均为0,可以不用加上)
即 k-1 = RL1*(n-1)! + RL2*(n-2)!+…+RLn*0!
代码描述:
public static int consMulti(int n){ int res = 1; for ( int i = 1;i <= n;i ++) { res *= i; } return res; }public static int kangtuo(int[] a) { int res = -2; for (int i = 0;i < a.length - 1;i ++) { int temp = 0; for ( int j = i + 1;j < a.length;j ++) { if (a[j] < a[i]) temp ++; } res += temp*consMulti( a.length - i - 1); } return res + 1; }
康托逆展开
已知排列在第k个位置,求出该排列a1,a2,…,an,相当于对刚才的过程逆向求解。
新建数组s[n],依次求出a1,a2,…an放入s[n]中存放。
由于
k-1 = RL1*(n-1)! + RL2*(n-2)!+… +RLn*0!
令k = k-1,则 k = RL1*(n-1)! + RL2*(n-2)!+… +RLn*0!
此时,k已知,n已知,
RL1 = k / (n-1)!
RL1代表a1后面比a1小的数的个数,此时s[0] = a1 = RL1+1;
k = k % (n-1)!
RL2 = k / (n-2)!
RL2代表a2后面比a2小的数的个数,但是此时a2前面也可能存在比a2小的数LL2,a2 = LL2 + RL2 + 1,
0 <= LL2 <=L2(L2表示a2 左边的数的个数), 从LL2 = 0开始假设,LL2 = 0时,此时a2 = 0 + RL2 + 1,(1)遍历 a2 左边数字X,如果存在X == a2, 或者小于a2的数字个数C != LL2, 则此假设不成立,LL2 ++,回归(1),找到正确 a2 后存入s[1];
……….
依次求得Rli 并找到ai存入s[i-1];
……….
由于RLn = 0, 最后直接将{1,2,…, n} 中未出现的数字存入s[n-1];
代码如下:
public static int[] kthPermu(int n, int k) { k -= 1; int[] res = new int[n]; int num; for (int i = 0; i < n - 1; i++) { num = Math.floorDiv(k, consMulti(n - 1 - i)); if (i == 0) { res[i] = num + 1; } else { for (int j = num + 1; j <= (num + i + 1); j++) { int leftNum = 0; boolean equal = false; for (int h = 0; h < i; h++) { if (res[h] < j) { leftNum++; } else if (res[h] == j) { equal = true; break; } } if (equal) continue; int tempJ = (leftNum + num) + 1; if (tempJ == j) { res[i] = j; break; } } } k %= consMulti(n - 1 - i); } int last = -1; for (int i = 1; i <= n; i++) { boolean flag = false; for (int j = 0; j < n - 1; j++) { if (res[j] == i) { flag = true; break; } } if (!flag) { last = i; break; } } res[n - 1] = last; return res; }
- 康托展开和康托逆展开解决第K个排列问题
- 全排列剖析:求n个数第k个排序----康托展开
- 全排列剖析:求n个数第k个排序----康托展开
- nyoj__139__143__康托展开和康托逆展开
- 康托展开和康托逆展开
- 康托展开和康托逆展开
- 康托展开 & 康托逆展开
- 康托展开 康托逆展开
- 康托展开 全排列
- 排列(康托展开)
- n个不重复的字符全排列问题 康托展开小结
- 关于全排列问题的总结(康托展开)
- 康托展开和逆康托展开
- 康托展开和逆康托展开
- 康托展开和逆康托展开
- 康托展开和逆展开
- 康托展开和逆康托展开
- 康托展开和逆康托展开
- md-dialog
- Fabonacci 数列问题
- MERGE INTO用法和举例
- POJ 2155 二维数组
- Qt之保存/恢复窗口的几何形状
- 康托展开和康托逆展开解决第K个排列问题
- 21分钟 MySQL 入门教程
- 设计模式实现——单例模式
- 2个域名2个网站共用一个空间的方法
- application is modifying the autolayout engine from a background thread, which can lead to engine co
- Linux之绝处逢生------SysRq
- 经典排序算法小结
- 3.保护模式1----pm.inc分析
- 将两个正整数的最大公约数表示成两个数的线性组合