报告错误
如果你发现该网页中存在错误/显示异常,可以从以下两种方式向我们报告错误,我们会尽快修复:
- 使用 CS Club 网站错误 为主题,附上错误截图或描述及网址后发送邮件到 286988023@qq.com
- 在我们的网站代码仓库中创建一个 issue 并在 issue 中描述问题 点击链接前往Github仓库
题目大意
题目会给一个字符串
S
和 整数K
,让你找出S
的所有可能的排列组合中排字典序第K
位的字符串,时间限制2sec
\(1\leqslant \vert S\vert \leqslant 8\) 比如aab 2
, aab的排列方式有{aab, aba, bba} 字典序第二位就是aba
思路
尝试列出S的所有排列组合 (比如abc) {abc, acb, bac, bca, cab, cba}
一开始想到的是循环,对于每一位,遍历一边arr里可能的元素,如果之前出现过就跳过。但是复杂度是
O(n^n)
观察 {abc, acb, bac, bca, cab, cba} 可以发现从第一个字符起每个字符分别与它后面的字符交换就可以列出所有可能的排序。 每交换一次定住前面一个字符再把后面的所有字符进行全排列,最后交换回来,避免重复。复杂度
O(n!)
代码
import java.util.*;
import java.io.*;
public class abc215c{
public static String[] letters;
public static ArrayList<String> ans = new ArrayList<>();
public static HashSet<String> visited;
public static void swap(int a, int b){
String temp = letters[a];
letters[a] = letters[b];
letters[b] = temp;
}
public static void perm(int l, int r){
if(l == r){
int len = visited.size();
String temp = "";
for(String j : letters) temp += j;
visited.add(temp);
if(visited.size() > len) ans.add(temp);
}else{
for(int i = l; i <= r; i++){
swap(l, i);
perm(l+1, r);
swap(l, i);
}
}
}
public static void main(String[] args) throws IOException{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
String[] items = br.readLine().split(" ");
String S = items[0];
int K = Integer.parseInt(items[1]);
visited = new HashSet<>();
letters = S.split("");
perm(0,S.length()-1);
Collections.sort(ans);
System.out.println(ans.get(K-1));
}
}