题意整理。
- 输入一个字符串数组以及一个待查找的单词。
- 求该单词的所有兄弟单词中的第k个。
- 定义一个单词的“兄弟单词”为:交换该单词字母顺序,而不添加、删除、修改原有的字母就能生成的单词。
方法一(计数+排序)
1.解题思路
- 首先定义一个方法,用于检查是否是兄弟单词。该方法需要定义一个计数数组,字符串s1中对应字符出现次数加1,字符串s2中对应字符出现次数减1,然后遍历整个计数数组,如果某个位置的值不为0,说明不是兄弟单词。
- 根据定义的检查方法,遍历输入的字符串数组,将所有的兄弟单词加入到一个list容器。list容器的大小即是兄弟单词的个数。
- 最后对list容器进行排序,输出索引位置k对应的值即是第k个兄弟单词。
图解展示:
2.代码实现
import java.util.Scanner;
import java.util.ArrayList;
import java.util.Collections;
public class Main{
public static void main(String[] args){
//标准输入
Scanner sc=new Scanner(System.in);
while(sc.hasNext()){
//单词的个数n
int n=sc.nextInt();
//存储输入的n个单词
String[] arr=new String[n];
for(int i=0;i<n;i++){
arr[i]=sc.next();
}
//待查找的单词x
String s=sc.next();
//数字k
int k=sc.nextInt();
//新建list,用于存储兄弟单词
ArrayList<String> list=new ArrayList<>();
for(int i=0;i<arr.length;i++){
if(!arr[i].equals(s)){
if(match(arr[i],s)){
list.add(arr[i]);
}
}
}
//对兄弟单词进行排序
Collections.sort(list);
//打印兄弟单词个数
System.out.println(list.size());
if(list.size()>=k){
//打印第k个兄弟单词
System.out.println(list.get(k-1));
}
}
}
//检查是否是兄弟单词
public static boolean match(String s1,String s2){
//计数数组
int[] count=new int[26];
for(int i=0;i<s1.length();i++){
//s1字符在对应位置计数加1
count[s1.charAt(i)-'a']++;
}
for(int i=0;i<s2.length();i++){
//s2字符在对应位置计数减1
count[s2.charAt(i)-'a']--;
}
for(int i=0;i<26;i++){
//如果不为0,说明两字符串中有某个字符出现次数不相等,不是兄弟单词
if(count[i]!=0){
return false;
}
}
return true;
}
}
3.复杂度分析
- 时间复杂度:输入的字符串长度为常数级别,所以检查方法的时间复杂度为,需要遍历整个字符串数组,假设数组长度为n,遍历的时间复杂度为。最坏情况下,兄弟单词的个数为n,对其进行排序的时间复杂度为,所以时间复杂度为。
- 空间复杂度:最坏情况下,需要额外大小为n的list容器,所以空间复杂度为。
方法二(利用io流)
1.解题思路
思路和方法一基本一致,不同的是通过io流操作来处理输入的数据。
2.代码实现
import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
public class Main{
public static void main(String[] args) throws Exception{
//io输入
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
String s;
while((s=br.readLine())!=null){
String[] str=s.split(" ");
//单词的个数n
int n=Integer.parseInt(str[0]);
//存储输入的n个单词
String[] arr=new String[n];
for(int i=0;i<n;i++){
arr[i]=str[i+1];
}
//待查找的单词x
String x=str[n+1];
//数字k
int k=Integer.parseInt(str[n+2]);
//新建list,用于存储兄弟单词
ArrayList<String> list=new ArrayList<>();
for(int i=0;i<arr.length;i++){
if(!arr[i].equals(x)){
if(match(arr[i],x)){
list.add(arr[i]);
}
}
}
//对兄弟单词进行排序
Collections.sort(list);
//打印兄弟单词个数
System.out.println(list.size());
if(list.size()>=k){
//打印第k个兄弟单词
System.out.println(list.get(k-1));
}
}
}
//检查是否是兄弟单词
public static boolean match(String s1,String s2){
//计数数组
int[] count=new int[26];
for(int i=0;i<s1.length();i++){
//s1字符在对应位置计数加1
count[s1.charAt(i)-'a']++;
}
for(int i=0;i<s2.length();i++){
//s2字符在对应位置计数减1
count[s2.charAt(i)-'a']--;
}
for(int i=0;i<26;i++){
//如果不为0,说明两字符串中有某个字符出现次数不相等,不是兄弟单词
if(count[i]!=0){
return false;
}
}
return true;
}
}
3.复杂度分析
- 时间复杂度:输入的字符串长度为常数级别,所以检查方法的时间复杂度为,需要遍历整个字符串数组,假设数组长度为n,遍历的时间复杂度为。最坏情况下,兄弟单词的个数为n,对其进行排序的时间复杂度为,所以时间复杂度为。
- 空间复杂度:最坏情况下,需要额外大小为n的list容器,所以空间复杂度为。