题目:
输入一个英文句子,输出重复的字母(不包括空格)和重复次数,
结果按次数倒序(从大到小)排列。
例如,输入“I am a student”,输出 a 2 t 2。
分析
要点有两个:
- 统计字符即次数
- 我使用了两种方法来统计次数 ,如下:
1. 利用Map<Character, Integer>,存放字符及其出现次数
2. 先将字符排序,再用两个指针一前一后,得出字符的出现次数 - 按次数倒序排列(从大到小)
- 如果是顺序,直接使用Arrays.sort()即可,但题目要求是倒序,所以考虑自定义比较器Comparator
解题:
package com.guo.bishi;
import java.util.*;
/**
* @Author FireLightGuo
* @Date 2021/10/29 21:15
* 题目:输入一个英文句子,输出重复的字母(不包括空格)和重复次数,
* 结果按次数倒序(从大到小)排列。
* 例如,输入“I am a student”,输出 a 2 t 2。
**/
public class PrintRepeatedCharAndCount {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String sentence = sc.nextLine();
resolveByMap(sentence);
resolveByList(sentence);
}
// 解法1:使用Map
public static void resolveByMap(String sentence) {
sentence = sentence.replace(" ", ""); // 去掉空格
char[] chars = sentence.toCharArray(); // 转化为字符数组
//Map<Integer, Character> resultMap = new TreeMap<>(); // 错误,同样次数的字符会被覆盖, 因为key相同
Map<Character, Integer> resultMap = new HashMap<>();
for (char c : chars) {
if (resultMap.containsKey(c)) {
resultMap.put(c, resultMap.get(c) + 1);
} else {
resultMap.put(c, 1);
}
}
// 筛选出重复次数大于1的Entry,存放到list中,再对list进行逆序排序
List<Map.Entry<Character, Integer>> list = new ArrayList<>();
for (Map.Entry<Character, Integer> entry : resultMap.entrySet()) {
if (entry.getValue() > 1) list.add(entry); // 题目要的是重复次数大于1的字符
}
// 自定义Comparator接口的匿名内部类,实现倒序排列
list.sort(new Comparator<Map.Entry<Character, Integer>>() {
@Override
public int compare(Map.Entry<Character, Integer> o1, Map.Entry<Character, Integer> o2) {
int count1 = o1.getValue();
int count2 = o2.getValue();
return count2 - count1; // ==> -(count1 - count2)
}
});
System.out.println(list);
}
// 解法2:使用List
public static void resolveByList(String sentence) {
sentence = sentence.replace(" ", ""); // 去掉空格
char[] chars = sentence.toCharArray(); // 转化为字符数组
Arrays.sort(chars); // 字符排序,方便统计重复次数
List<String> resultList = new ArrayList<>();
int count = 1; // 重复次数,初始为1
// 统计次数的核心代码,前后指针i,j,(注意这里的chars是排好序的)
// 如:my name is stephen curry
// 去掉空格,排序后:aceeehimmnnprrsstuyy
for (int i = 0, j = 1; j < chars.length; i++, j++) {
if (chars[i] == chars[j]) {
count++;
} else if (count > 1) { // 重复次数大于1,添加到list中
// 字符拼接为字符串,格式为 次数 + 字符,
// 如e出现了12次,则添加"12e"到list中
// 注意这里的 ""+ ,如果直接count+chars[i]得到的是整数
resultList.add("" + count + chars[i]); // eg: 2a, 3c, 14f ...
count = 1;
}
}
resultList.sort(new descComparator()); // 自定义递减排列器
for (String str : resultList) {
// 截取字符及对应次数,如"126a", 即字符a,出现次数126
// str.charAt(str.length()-1)截取字符
// str.substring(0,str.length()-1)截取次数
System.out.print(str.charAt(str.length()-1) + " " +
str.substring(0,str.length()-1) + " ");
}
}
static class descComparator implements Comparator<String> {
@Override
public int compare(String o1, String o2) {
int count1 = Integer.parseInt(o1.substring(0, o1.length()-1));
int count2 = Integer.parseInt(o2.substring(0, o2.length()-1));
return count2 - count1;
}
}
}
总结
这道题是笔试的一道编程题,难度不大,但当时有一些细节没注意到,现在把这道题解出来了,算是弥补了这个遗憾。
希望对大家有帮助