前端云笔记:记录一道前缀树的题目

286 阅读1分钟

题目

假设有一个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'))