个人博客首页: KJ.JK
专栏介绍: 华为OD机试真题汇总,定期更新华为OD各个时间阶段的机试真题,每日定时更新,本专栏将使用C语言进行更新解答,包含真题,思路分析,代码参考,欢迎大家订阅学习
给定参数n,从1到n会有n个整数:1,2,3,…,n,这n个数字共有n!种排列。
按大小顺序升序列出所有排列的情况,并一一标记,
当n=3时,所有排列如下:
“123” “132” “213” “231” “312” “321”
给定n和k,返回第k个排列。
输入
输入两行,第一行为n,第二行为k,
给定n的范围是[1,9],给定k的范围是[1,n!]。
输出
输出排在第k位置的数字。
输入
3
3
输出
213
说明:
3的排列有123,132,213…,那么第三位置就是213
输入
2
2
输出
21
说明:
2的排列有12,21,那么第二位置的为21。
首先,我们可以计算出给定参数n的总排列数,即n的阶乘,记为totalPermutations。
创建一个大小为n的数组nums,用于存储当前排列。
创建一个大小为n的布尔数组used,用于标记数字是否已经被使用过。初始时,所有元素都为false。
定义一个整数变量count,用于计数当前排列是第几个。
创建一个大小为n的结果数组result,用于存储第k个排列。
使用回溯算法,通过递归生成所有的排列。具体步骤如下:
如果当前深度depth等于n,表示已经生成了一个完整的排列,将count加1。
如果count等于k,表示已经找到第k个排列,将当前排列复制到结果数组result中,并结束递归。
否则,对于每个数字i(从1到n),如果数字i没有被使用过(used[i]为false),则将其放入当前排列的第depth个位置,将used[i]标记为true,并递归生成下一个位置的数字。
在递归返回之前,将used[i]重置为false,以便其他排列可以使用该数字。
最后,返回结果数组result。
#include
#include
int factorial(int n) {
if (n == 0 || n == 1)
return 1;
else
return n * factorial(n - 1);
}
void getPermutation(int n, int k, int* nums, int* used, int depth, int* count, int* result) {
if (depth == n) {
(*count)++;
if (*count == k) {
for (int i = 0; i < n; i++) {
result[i] = nums[i];
}
}
return;
}
for (int i = 1; i <= n; i++) {
if (!used[i]) {
used[i] = 1;
nums[depth] = i;
getPermutation(n, k, nums, used, depth + 1, count, result);
used[i] = 0;
}
}
}
int* findKthPermutation(int n, int k) {
int totalPermutations = factorial(n);
if (k > totalPermutations) {
return NULL; // 如果k大于总排列数,则返回空指针
}
int* nums = (int*)malloc(n * sizeof(int));
int* used = (int*)calloc(n + 1, sizeof(int));
int* result = (int*)malloc(n * sizeof(int));
int count = 0;
getPermutation(n, k, nums, used, 0, &count, result);
free(nums);
free(used);
return result;
}
int main() {
int n, k;
scanf("%d", &n);
scanf("%d", &k);
int* result = findKthPermutation(n, k);
if (result == NULL) {
printf("Invalid input\n");
} else {
for (int i = 0; i < n; i++) {
printf("%d", result[i]);
}
printf("\n");
}
free(result);
return 0;
}