题目
给定一个段落 (paragraph) 和一个禁用单词列表 (banned)。返回出现次数最多,同时不在禁用列表中的单词。
题目保证至少有一个词不在禁用列表中,而且答案唯一。
禁用列表中的单词用小写字母表示,不含标点符号。段落中的单词不区分大小写。答案都是小写字母。
输入:
paragraph = "Bob hit a ball, the hit BALL flew far after it was hit."
banned = ["hit"]
输出: "ball"
解释:
"hit" 出现了3次,但它是一个禁用的单词。
"ball" 出现了2次 (同时没有其他单词出现2次),所以它是段落里出现次数最多的,且不在禁用列表中的单词。
注意,所有这些单词在段落里不区分大小写,标点符号需要忽略(即使是紧挨着单词也忽略, 比如 "ball,"),
"hit"不是最终的答案,虽然它出现次数更多,但它在禁用单词列表中。
自己想法:(哈希表+hashMap+遍历) 但这样用时比较慢
先创建一个哈希表,将banned中的每一个单词加进去, 然后利用正则表达式,将paragraph分割成一个个单词。再遍历分割后paragraph的String数组,看看是否存在于hashset中,若不在就加入hashMap并计数。
代码:
执行用时:21 ms, 在所有 Java 提交中击败了7.75%的用户 内存消耗:41.2 MB, 在所有 Java 提交中击败了50.24%的用户 通过测试用例:47 / 47
class Solution {
public String mostCommonWord(String paragraph, String[] banned) {
String regex = "[\\s\\p{Punct}]"; // \\s 空格符 p{Punct}标点符号
String[] str = paragraph.split(regex); //分割字符串
HashSet<String> hashSet = new HashSet<>();
HashMap<String, Integer> hm = new HashMap<>();
for (String ele : banned)
hashSet.add(ele); //加入禁用单词
for (String words : str) {
String word = words.toLowerCase(); //转成小写字母
if (!word.equals("")&&!hashSet.contains(word)) { //不包含
hm.put(word, hm.getOrDefault(word, 0) + 1); //记录次数
}
}
Set<String> strs = hm.keySet();
int max=0;
String s=null;
for(String ele :strs) {
if (hm.get(ele) > max) {
max = hm.get(ele);
s=ele;
}
}
return s;
}
}
在一开始的时候,判断不包含的条件中我只限制了哈希表if (!hashSet.contains(word))
但会发现一个问题:split(regex)——regex = "[\\s\\p{Punct}]"; // \\s 空格符 p{Punct}标点符号 会分割出“”(空字符串)【例如bob. hit 先遇到了. 分割为bob和“”】,这会导致后面遍历取最大值时出错。所以需要补上 if (!word.equals("")&&!hashSet.contains(word))
看了一下别人的题解,思路都差不多,发现这题的执行时间普遍比较久
优化一下:先对原字符串进行处理:
执行用时:13 ms, 在所有 Java 提交中击败了33.22%的用户
1.全部转为小写字母 2.将标点符号用“ ”代替 3.再进行分割
class Solution {
public String mostCommonWord(String paragraph, String[] banned) {
paragraph = paragraph.toLowerCase();
paragraph = paragraph.replaceAll("\\p{Punct}"," ");//正则表达式 将所有标点符号使用 空格代替
String[] words = paragraph.split(" ");
HashMap<String,Integer> map = new HashMap<>();//存储 string-次数 键值对
HashSet<String> bannedSet = new HashSet<>();
for(String word:banned){
bannedSet.add(word);
}
int max = 0;
String maxWord = null;
//记录对应的单词和出现次数
for(String word : words){
if(word == "") continue;
if(map.containsKey(word)){
map.put(word,map.get(word)+1);
}else{
map.put(word,1);
}
if(map.get(word) > max){
if(!bannedSet.contains(word)){
maxWord=word;
max = map.get(word);
}
}
}
System.out.println(map);
return maxWord;
}
}