该代码的目标是解决排列组合中的第 k 个排列问题(即字典序第 k 小的排列)。问题描述是:给定正整数 n 和 k,返回从 [1, 2, …, n] 这些数字组成的所有排列中按字典序排列的第 k 个排列。
主要思路:
使用阶乘数组:通过预计算阶乘(factorial),快速确定某一位数字对应的索引范围。 按位置逐位构造排列: 确定第 i 位数字时,根据当前剩余排列数量可以计算该位应该选取的数字。 从剩余数字中取出对应的数字,并从候选数字列表中移除。 递归更新剩余的索引值 k: 计算余数,缩小问题规模,继续处理剩余的数字
n =int(input())# 输入 n,表示排列的长度
k =int(input())# 输入 k,表示需要找的第 k 个排列# 初始化数字数组 [1, 2, ..., n]
numbers =[i +1for i inrange(n)]# 计算阶乘数组,用于快速确定当前数字的索引范围
factorial =[1]*(n +1)for i inrange(2, n +1):
factorial[i]= factorial[i -1]* i
# 初始化结果数组,用于存储最终的排列结果
result =[]# 因为索引从 0 开始,所以 k 减 1
k -=1# 遍历每一位,逐步确定每一位数字for i inrange(1, n +1):# 计算当前位需要选择的数字索引
index = k // factorial[n - i]# 将该数字添加到结果数组中
result.append(str(numbers[index]))# 从候选数字中移除已选择的数字
numbers.pop(index)# 更新 k 的值,缩小问题规模
k %= factorial[n - i]# 将结果数组拼接成字符串并输出print("".join(result))
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
java解法
解题思路
目标是找到 [1, 2, …, n] 的所有排列中,按字典序排序后的第 k 个排列。解决方式与 Python 版本相似,采用递归的方法逐步构造结果。
主要步骤:
利用阶乘的性质确定排列范围: 对于长度为 n 的排列,前 n-1 位的排列总数为 (n-1)!。 根据 (k-1) / (n-1)! 可以计算出当前排列的起始数字的索引。 递归生成排列: 每次选定一个数字,将其从候选列表中移除。 根据剩余的 k 值,递归处理剩下的数字。 拼接结果: 每次递归选出的数字依次拼接,最终形成完整的排列。
importjava.util.ArrayList;importjava.util.List;importjava.util.Scanner;publicclassMain{publicstaticvoidmain(String[] args){Scanner sc =newScanner(System.in);// 创建输入对象int n = sc.nextInt();// 输入 n,表示排列的长度int k = sc.nextInt();// 输入 k,表示需要找的第 k 个排列List<Integer> nums =newArrayList<>();// 初始化数字列表 [1, 2, ..., n]for(int i =1; i <= n; i++) nums.add(i);// 调用函数获取第 k 个排列并输出System.out.println(getPermutation(nums, k));}/**
* 获取第 k 个排列
* @param nums 候选数字列表
* @param k 第 k 个排列(从 1 开始)
* @return 第 k 个排列的字符串
*/publicstaticStringgetPermutation(List<Integer> nums,int k){// 如果列表为空,返回空字符串(递归终止条件)if(nums.size()==0)return"";int n = nums.size();// 当前列表的长度int f =factorial(n -1);// 计算 (n-1)!,用于确定当前数字的范围int index =(k -1)/ f;// 确定当前位数字的索引int chosen = nums.remove(index);// 从候选数字列表中移除选择的数字
k = k - index * f;// 更新 k,处理剩余部分// 返回当前选择的数字和剩余数字的排列结果return chosen +getPermutation(nums, k);}/**
* 计算 n 的阶乘
* @param n 非负整数
* @return n 的阶乘
*/publicstaticintfactorial(int n){int result =1;// 初始化结果为 1for(int i =2; i <= n; i++) result *= i;// 从 2 开始累乘到 nreturn result;}}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
评论记录:
回复评论: