1.在控制台输入一个字符串,字符串长度小于等于12,并且输入一个数字n,求出字典序的第n个全排列
2.我们可以求出全部的全排列之后排序后输出第k个全排列,但是这样会非常浪费时间和空间,这里使用另外的一种方法,那就是前缀法求解第k个全排列
从头开始扫描字符串,假如当前字符没有出现,那么把这个字符加入到字符串中,假如以ABC为例,那么具体的前缀的形成过程如下:
从ABC调用完返回到上一层AB那么发现有兄弟那么继续下一次循环递归调用形成了ACB
那么通过上面的分析可以知道我们可以使用递归来解决上面的问题,而且每一次都是从数组的开始扫描:循环中使用递归
这里要注意的是有重复字符的处理
3.具体的代码如下:
import java.util.Scanner;
public class Main{
static int count = 0;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s = sc.nextLine();
int n = sc.nextInt();
getKPermutation("", s.toCharArray(), n);
}private static void getKPermutation(String prefix, char arr[], int n) {
if(prefix.length() == arr.length){
count++;
if(count == n){
System.out.println(prefix);
System.exit(0);
}
}
//如果字符集的字符长度小于数组中的字符串长度那么这个字符可以使用
for(int i = 0; i < arr.length; i++){
char ch = arr[i];
//处理字符重复的情况
if(count(prefix, ch) < count(arr, ch)){
getKPermutation(prefix + ch, arr, n);
}
}
}private static int count(char[] arr, char ch) {
int cnt = 0;
for(int i = 0; i < arr.length; i++){
if(ch == arr[i]){
cnt++;
}
}
return cnt;
}private static int count(String prefix, char ch) {
int cnt = 0;
for(int i = 0; i < prefix.length(); i++){
if(ch == prefix.charAt(i)){
cnt++;
}
}
return cnt;
}
}