一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天,点击查看活动详情
一、题目描述
- 给定一个段落 (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"不是最终的答案,虽然它出现次数更多,但它在禁用单词列表中。
- 输入:
- 提示:
1 <= 段落长度 <= 10000 <= 禁用单词个数 <= 1001 <= 禁用单词长度 <= 10- 答案是唯一的, 且都是小写字母 (即使在
paragraph里是大写的,即使是一些特定的名词,答案都是小写的。) paragraph只包含字母、空格和下列标点符号!?',;.- 不存在没有连字符或者带有连字符的单词。
- 单词里只包含字母,不会出现省略号或者其他标点符号。
二、思路分析:
- 要求返回给定字符串中出现次数最多的单词,并且该单词不能出现在禁用列表中
- 首先是不是需要将字符串段落中的单词提取出来,然后才能统计每个单词出现的次数和是不是在禁用列表中
- 怎么做?单词和单词之间的区分有两种方式,一种是空格,一种是英文符号
!?',;. - 去除掉所有的符号,然后利用字符串的
spilt方法将每个单词提取出来
- 将段落字符串中的每个单词提出出来之后怎么办?
- 题目描述说单词是不区分大小写的,也就是
All和all表示同一个单词,all出现了两次 - 所以还需要将大写的单词或者部分大写字母转化成小写字母
- 题目描述说单词是不区分大小写的,也就是
- 然后呢?
- 得到一个字符串的单词数组,怎么统计每个单词的出现次数?统计后怎么得到最高的出现次数的那个单词?并且需要验证这个最高的次数多单词是不是禁用单词,如果是,那就取出现次数第二高的,如果第二高的也是禁用单词,取第三高的。。。。
- 这里做的是先遍历字符串数组,用
toLocaleLowerCase方法将大写字母转化为小写字母 - 然后利用
Set去重后得到一个去重后的新数组 - 遍历去重前的数组和禁用数组,如果去重前的数组项在禁用数组内出现了,那么这个单词一定不是常用单词,统统删掉
- 遍历删除禁用单词后的未去重单词列表和去重单词列表,统计每个单词出现的次数和单词,用对象形式储存在数组中
- 将保存答案的数组排序,排序字段为对象中的
index属性,保存的就是该单词出现的次数 - 最后将排序后的数组内对象的
value返回即可
三、AC 代码:
function mostCommonWord(paragraph: string, banned: string[]): string {
let str = paragraph.replace(/[!?',;.]/g, ' ');
let strArr = str.split(' ').map(item => item.toLocaleLowerCase());
let removeArr = [... new Set(strArr)];
let maxCount = [];
for(let i = 0; i < banned.length; i++){
for(let j = 0; j < removeArr.length; j++){
if(banned[i] === removeArr[j] || removeArr[j] === ''){
removeArr.splice(j, 1);
j--
}
}
}
for(let i = 0; i < removeArr.length; i++){
let count = 0;
for(let j = 0; j < strArr.length; j++){
if(removeArr[i] === strArr[j]){
count++
}
}
maxCount.push({
'index': count,
'value': removeArr[i]
})
}
maxCount.sort((a, b)=> b.index - a.index)
return maxCount[0].value
};
四、总结:
- 需要注意的地方:
- 刚开始将所有符号都替换成空字符,然后提交的时候报错了,错误用例是
"a, a, a, a, b,b,b,c, c"和["a"] - 原因是有的单词或者字母之间只有符号,替换成空字符后两个单词就会变成一个单词
- 后面将所有符号替换成空格,然后再按照空格进行切割
- 这样也会出现切割出来数组中有空字符的情况,所以再遍历删除禁用列表时一起把空字符也删掉
- 刚开始将所有符号都替换成空字符,然后提交的时候报错了,错误用例是
- 简单难度,就是方法有点麻烦,更多解题方式,移步题解区