题目
假设有一个10万个元素的有序数组,现在需要输入一个搜索条件,找出符合这个搜索条件的第一项。例如:
搜索‘abc’, 在数组['abca', 'abcb', 'abcc', 'abcd']中找出'abca'
解法
建立一个前缀树的结构,该前缀树具有insert和search两个方法(以下代码已经实测通过)
const words = ['abcd', 'abca']
function Node(val, isWord) {
this.val = val;
this.children = {};
this.isWord = isWord
}
function Trie() {
this.root = new Node(null, false)
}
Trie.prototype.insert = function(str) {
let curNode = this.root;
str = str.split('');
for (let i = 0; i < str.length; i++) {
const letter = str[i]
let hasLetter = curNode.children[letter]
if (!hasLetter) {
if (i === str.length - 1) {
curNode.children[letter] = new Node(letter, true)
} else {
curNode.children[letter] = new Node(letter, false)
}
}
curNode = curNode.children[letter];
}
}
Trie.prototype.search = function(word) {
word = word.split('');
let curNode = this.root;
for (let i = 0; i < word.length; i++) {
let letter = word[i];
// 前缀树中没有对应的字母,则说明该单词不在列表中
if (!curNode.children[letter]) {
return false;
}
// 前缀树中有对应的字母,则继续查下一个字母是否匹配
curNode = curNode.children[letter]
// 查到了最后一个字母
if (i === word.length - 1) {
// 查询的单词是列表中某些单词的一部分,不是全部
if (!curNode.isWord) {
while (true) {
for (let key in curNode.children) {
word.push(key);
curNode = curNode.children[key];
// 找出第一个符合的字母即可
break;
}
// 查询到了列表中某个单词的最后一个字母
if (curNode.isWord) {
break;
}
}
}
return word.join('');
}
}
}
// 每次建立的前缀树都是一个对象,只有一个root属性
let tree = new Trie();
// 通过insert方法不断插入元素
words.forEach((word, index) => {
tree.insert(word, index)
})
console.log(tree.search('abc'))