携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第23天,点击查看活动详情
题目描述
在英语中,我们有一个叫做 词根(root) 的概念,可以词根 后面 添加其他一些词组成另一个较长的单词——我们称这个词为 继承词(successor)。例如,词根 an,跟随着单词 other(其他),可以形成新的单词 another(另一个)。
现在,给定一个由许多词根组成的词典 dictionary 和一个用空格分隔单词形成的句子 sentence。你需要将句子中的所有继承词用词根替换掉。如果 继承词 有许多可以形成它的 词根,则用 最短 的词根替换它。
你需要输出替换之后的句子。
示例 1:
输入:dictionary = ["cat","bat","rat"], sentence = "the cattle was rattled by the battery"
输出:"the cat was rat by the bat"
示例 2:
输入:dictionary = ["a","b","c"], sentence = "aadsfasf absbs bbab cadsfafs"
输出:"a a b c"
解题思路——Set枚举
这题很直接的,我们先将 sentence 字符串通过 split 分割成一个个的单词数组。然后遍历这个单词数组,对于其中的每个单词,都去 dictionary 里找有没有和它公共前缀相同的最短的单词,如果有的话则返回这个词典中最短的公共前缀的单词,否则就返回原单词。
这里为了减少查询的时间,可以通过将 dictionary 中的所有词存入 Set 集合中,后续遍历单词数组时,分别去查找该单词的 前一个字符、前两个字符、前三个字符...前n个字符是否存在于该 Set 集合中。
题解
var replaceWords = function(dictionary, sentence) {
const dictionarySet = new Set();
for (const root of dictionary) {
dictionarySet.add(root);
}
const words = sentence.split(" ");
for (let i = 0; i < words.length; i++) {
const word = words[i];
for (let j = 0; j < word.length; j++) {
if (dictionarySet.has(word.substring(0, 1 + j))) {
words[i] = word.substring(0, 1 + j);
break;
}
}
}
return words.join(' ');
};
解题思路——前缀树(字典树、Trie树)
从 手摸手提桶跑路——LeetCode208.实现Trie(前缀树) 过来的同学应该都理解了什么是 Trie 树。
这里通过 Trie 树我们能够快速找到存在于 Trie 树中的所有单词,而 Set 枚举中需要不断的通过 substring 截取前缀去 Set 里找有没有对应的元素,这个效率就很低了。
那么用 Trie 树我们应该怎么去写呢?来看看步骤:
- 创建一个
Trie树。 - 然后遍历
dictionary将所有元素添加进Trie树。 - 分割
sentence为数组并遍历,对每个元素去Trie树中查询 最短路径 的前缀,并对该单词进行替换,如果没有查找到对应前缀开头的单词,就返回原字符串。
题解
class Trie {
constructor() {
this.children = {};
this.isEnd = false;
}
}
var replaceWords = function(dictionary, sentence) {
const trie = new Trie();
for(let word of dictionary) {
let temp = trie;
for(let w of word) {
if(temp.children[w] === void 0) {
temp.children[w] = new Trie();
}
temp = temp.children[w];
}
temp.isEnd = true;
}
const arr = sentence.split(" ");
return arr.map(word=>{
return findRoot(word, trie);
}).join(" ")
};
const findRoot = (word, trie) => {
let res = '';
for (let w of word) {
if (trie.children[w] != void 0) {
res += w;
trie = trie.children[w];
if (trie.isEnd) return res;
} else {
return word;
}
}
return word;
}