算法每一题,成长每一天~
C0E33 第k个排列
真题链接:【持续更新】2024华为 OD 机试E卷 机考真题库清单(全真题库)
思路
Java
package com.ccr.paper_f;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class C0E33 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int k = in.nextInt();
List<Integer> number = new ArrayList<>(); // 1~n
for (int i = 0; i < n; i++) {
number.add(i, i + 1);
}
// 阶乘
int[] multi = new int[n + 1]; // multi[x] = x!
multi[0] = 1;
multi[1] = 1;
for (int i = 2; i <= n; i++) {
multi[i] = i * multi[i - 1];
}
int[] result = new int[n];
int r = k - 1; // 余数。 输入的 k 是从1算起,这里从索引位0开始算,所以起始 k-1
// 从高位开始,计算每一位的数字
for (int i = n; i >= 1; i--) {
int x = multi[i - 1]; // 计算第i位时,除数为 (i-1)的阶乘
int idx = r / x;
result[i - 1] = number.remove(idx); // 用一个拿掉一个
r = r % x;
}
// 从后往前打印
for (int i = result.length - 1; i >= 0; i--) {
System.out.print(result[i]);
}
}
}
总结
1、因为是完全的 从小到大 排列所有组合,所以对于每一位数来说,也是从小到大的。所以对于 第 k 个数,换算出每一位的位置索引,即可求解。
2、这里利用 ArrayList .remove(idx)
特性,排序的同时,方便按 索引值 来获取并移除 数据。
算法要多练多练多练!!