求排列的第k个序列。给定26个字母的前n个字符(不重复),对其进行全排列,并按字典排序,求第k个排列的序列。例如,n=3时,字符为abc,其排列(按字典排序)为abc、acb、bac、bca、cab、cba,则第1个排列为abc,第2个排列为acb,第6个排列为cba。其中1≤n≤26,1≤k≤2^32−1。若k>n!,则显示最后一个排列。
下面这段代码在实现上述要求时,大多数情况下结果正确,却在个别情况下输出错误结果。这是为什么?
#include <stdio.h>
unsigned long facs[13] = {0, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600};
int range(unsigned long num) {
int floor = 12;
for (int i = 0; i < 12; i++) {
if (num > facs[floor] && (floor == 12 || num <= facs[floor+1])) {
return floor;
}
else {
floor -= 1;
}
}
return -1;
}
int main() {
int n;
unsigned long k;
scanf("%d,%lu", &n, &k);
if (n < 13 && k >= facs[n]) {
for (int i = 0; i < n; i++) {
printf("%c", n + 96 - i);
}
return 0;
}
int k_floor = range(k);
int list[n];
int remain_len = k_floor + 1;
for (int i = 0; i < n - remain_len; i++) {
list[i] = i;
}
int remain[remain_len];
for (int i = 0; i < remain_len; i++) {
remain[i] = n - remain_len + i;
}
unsigned long quot, rem, place, d;
for (int i = n - remain_len; i < n; i++) {
if (k == 0) {
for (int j = remain_len - 1; j >= 0; j--) {
if (remain[j] != -1) {
list[i] = remain[j];
remain[j] = -1;
break;
}
}
}
else if (k == 1) {
for (int j = 0; j < remain_len; j++) {
if (remain[j] != -1) {
list[i] = remain[j];
remain[j] = -1;
break;
}
}
}
else {
rem = k % facs[k_floor];
quot = (k - rem) / facs[k_floor];
if (rem == 0) {
place = quot;
}
else {
place = quot + 1;
}
d = 0;
for (int j = 0; j < remain_len; j++) {
if (remain[j] != -1) {
d += 1;
if (d == place) {
list[i] = remain[j];
remain[j] = -1;
break;
}
}
}
k = rem;
k_floor = range(k);
}
}
for (int i = 0; i < n; i++) {
printf("%c", list[i] + 97);
}
return 0;
}