您的位置:首页 > 其它

康托展开和康托逆展开解决第K个排列问题

2016-09-02 23:26 267 查看


集合{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
,依次求出a1,a2,…an放入s
中存放。

由于

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
;
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法 排列顺序