1. 题目描述
定义一个单词的“兄弟单词”为:交换该单词字母顺序(注:可以交换任意次),而不添加、删除、修改原有的字母就能生成的单词。
兄弟单词要求和原来的单词不同。例如: ab 和 ba 是兄弟单词。 ab 和 ab 则不是兄弟单词。
现在给定你 n 个单词,另外再给你一个单词 x ,让你寻找 x 的兄弟单词里,按字典序排列后的第 k 个单词是什么?
注意:字典中可能有重复单词。
数据范围: 1 ≤ n ≤ 1000 1≤n≤1000 1≤n≤1000 ,输入的字符串长度满足 1 ≤ l e n ( s t r ) ≤ 10 , 1 ≤ k < n 1≤len(str)≤10 , 1≤k<n 1≤len(str)≤10,1≤k<n
输入描述: 输入只有一行。 先输入字典中单词的个数n,再输入n个单词作为字典单词。 然后输入一个单词x 最后后输入一个整数k。
输出描述: 第一行输出查找到x的兄弟单词的个数m 第二行输出查找到的按照字典顺序排序后的第k个兄弟单词,没有符合第k个的话则不用输出。
示例1:
输入:3 abc bca cab abc 1
输出:2
\space\space\space\space\space\space\space\space\space\space bca
示例2:
输入:6 cab ad abcd cba abc bca abc 1
输出:3
\space\space\space\space\space\space\space\space\space\space bca
说明:
abc的兄弟单词有cab cba bca,所以输出3
经字典序排列后,变为bca cab cba,所以第1个字典序兄弟单词为bca
2. 思路
- 暴力遍历法:逐个判断两个单词之间长度相等、总的ASCII码相等、去重后字母的总数相等。
- 优化后:根据题意,兄弟单词指的是:不删减、不修改的情况下,只通过调换字母顺序就可以转换。那么判断两个单词是否是兄弟单词,只需要判断两者重新排序后是否相等即可(注意排序后还要还原原先的值,不要存排序后的单词;或者存一个副本进行排序)。
注意:
- 在 Java 中,使用迭代器遍历集合时,不能直接修改集合的结构,否则就会抛出异常
ConcurrentModificationException
。 - 注意
toString()
的使用,与String.valueOf()
的不同之处。 - char[]是基本类型,默认使用的是Object类的equals方法,比较的是对象的地址值。如果要比较两个数组的内容,可以使用方法
Arrays.equals(a,b)
。
3. 代码
代码1:
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 存储所有数据
List<String> allDataList = new ArrayList<>();
while (in.hasNext()) {
allDataList.add(in.next());
}
Integer n = Integer.valueOf(allDataList.get(0));
int k = Integer.parseInt(allDataList.get(allDataList.size() - 1));
String x = allDataList.get(allDataList.size() - 2);
List<String> verifyWordList = new ArrayList<>();
List<String> waitVerifyWordsList = allDataList.subList(1, n + 1);
for (String word : waitVerifyWordsList) {
List<Character> wordList = str2CharList(word);
int wordInt = getAscii(word);
int xInt = getAscii(x);
List<Character> xList = str2CharList(x);
if (!word.equals(x) && word.length() == x.length() && xList.containsAll(wordList)
&& wordInt == xInt && wordList.stream().distinct().count() ==
xList.stream().distinct().count()) {
verifyWordList.add(word);
}
}
verifyWordList = verifyWordList.stream().distinct().collect(Collectors.toList());
Collections.sort(verifyWordList);
if (k > verifyWordList.size()){
System.out.println();
}
System.out.println(verifyWordList.size());
System.out.println(verifyWordList.get(k - 1));
}
private static List<Character> str2CharList(String s){
List<Character> targetList = new ArrayList<>();
for (char c : s.toCharArray()) {
targetList.add(c);
}
return targetList;
}
private static int getAscii(String s){
int res = 0;
for (char c : s.toCharArray()) {
res += c;
}
return res;
}
代码2(优化后):
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String s = in.nextLine();
String[] split = s.split(" ");
int n = Integer.parseInt(split[0]);
String x = split[split.length - 2];
int k = Integer.parseInt(split[split.length - 1]);
ArrayList<String> result = new ArrayList<>();
for (int i = 1; i <= n; i++) {
if (split[i].equals(x) || split[i].length() != x.length()){
continue;
}
if (isBrotherWord(split[i],x)){
result.add(split[i]);
}
}
Collections.sort(result);
System.out.println(result.size());
if (k <= result.size()){
System.out.println(result.get(k-1));
}
}
public static boolean isBrotherWord(String a, String b){
char[] aList = a.toCharArray();
char[] bList = b.toCharArray();
Arrays.sort(aList);
Arrays.sort(bList);
if (Arrays.equals(aList,bList)){
return true;
}else {
return false;
}
}
以上为个人学习分享,如有问题,欢迎指出:)