Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
一、题目描述:
819. 最常见的单词 - 力扣(LeetCode) (leetcode-cn.com)
给定一个段落 (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 <= 段落长度 <= 1000
- 0 <= 禁用单词个数 <= 100
- 1 <= 禁用单词长度 <= 10
- 答案是唯一的, 且都是小写字母 (即使在 paragraph 里是大写的,即使是一些特定的名词,答案都是小写的。)
- paragraph 只包含字母、空格和下列标点符号!?',;.
- 不存在没有连字符或者带有连字符的单词。
- 单词里只包含字母,不会出现省略号或者其他标点符号。
二、思路分析:
思路很清晰,就是将句子切割成单词,转小写,然后统计每个不在禁止单词列表中的单词的出现次数,返回次数最高的单词。 为了高效检查单词是否被禁止,使用了集合Set对象;切割单词时,用了js的split方法,该方法支持正则表达式,将连续的空格或标点符号作为分隔符,即可正确分割单词
三、AC 代码:
/**
* @param {string} paragraph
* @param {string[]} banned
* @return {string}
*/
var mostCommonWord = function(paragraph, banned) {
var bannedSet = new Set();
banned.forEach((v) => {
bannedSet.add(v);
});
var ans = "";
var count = new Map();
paragraph.split(/[!\?',;\.' ]+/).forEach((v) => {// 根据标点符号或空格切割成多个单词,转小写,计数
if (v == "") return;
v = v.toLocaleLowerCase();
if (bannedSet.has(v)) {
return;
}
count.set(v, count.has(v) ? count.get(v) + 1 : 1);
});
let maxC = 0;
[...count.entries()].forEach(([k, v]) => {// 找次数最多的单词
if (maxC < v) {
maxC = v;
ans = k;
}
})
return ans;
};