实现一个 Trie (前缀树),包含 insertsearch, 和 startsWith 这三个操作。

示例:

Trie trie = new Trie();

trie.insert("apple");
trie.search("apple");   // 返回 true
trie.search("app");     // 返回 false
trie.startsWith("app"); // 返回 true
trie.insert("app");   
trie.search("app");     // 返回 true

说明:

  • 你可以假设所有的输入都是由小写字母 a-z 构成的。
  • 保证所有输入均为非空字符串。

解题思路:

26叉树。使用26叉树储存英文单词,仅有小写字母,因此只有26个分支。主要的技术在于构造26叉树的结点。

struct TreeNode26 {
    char val;
    TreeNode26* next[26];
    bool isLast = false;
    TreeNode26(char v) {
        val = v;
        for (int i = 1; i <= 26; i++) {
            next[i - 1] = NULL;
        }
    }
    bool hasChild26() {
        for (int i = 1; i <= 26; i++) {
            if (next[i - 1]) return true;
        }
        return false;
    }
};

TreeNode26包含当前结点的字符val,isLast用于保存当前结点是否是单词末尾,以便于访问前缀。*next[26]是26个分支,代表下一个字符的所有可能性,数组下标0-25分别表示a-z26个英文单词的位置。

1. 插入单词。

从根结点开始,根结点一般不用。依次将字符串中的每一个字符放入26叉树中,直到遍历所有字符。将最后一个字符所在的结点的isLast属性设置为true,表明这个结点是一个单词的末尾。从这个结点开始一直查找他的父亲便可以得到整个单词(本题不需要)。

2. 查找单词

遍历整个单词,从根节点向下,依次查找他的孩子中是否有当前访问的字符。一旦遇到查找失败说明查找的单词不存在。如果能够查找到所有字母,并且最后一个结点是某一个单词的末尾(isLast==true),说明查找成功,否者它只是一个单词的前缀。

3. 查找前缀

遍历整个单词,从根节点向下,依次查找他的孩子中是否有当前访问的字符。一旦遇到查找失败说明查找的单词不存在。如果能够查找到所有字母,说明必然有这个前缀。

经测试,当前时刻, 小于56ms的代码运行时间均在56ms附近。

                    Leetcode:208.前缀树

C++代码

struct TreeNode26 {
    char val;
    TreeNode26* next[26];
    bool isLast = false;
    TreeNode26(char v) {
        val = v;
        for (int i = 1; i <= 26; i++) {
            next[i - 1] = NULL;
        }
    }
    bool hasChild26() {
        for (int i = 1; i <= 26; i++) {
            if (next[i - 1]) return true;
        }
        return false;
    }
};
class Trie {
public:
    TreeNode26 *root;
    /** Initialize your data structure here. */
    Trie() {
        root = new TreeNode26(' ');
    }
    /** Inserts a word into the trie. */
    void insert(string word) {
        int size = word.size();
        TreeNode26 * node = root;
        char ch;
        for (int i = 1; i <= size; i++) {
            ch = word[i - 1];
            if (!node->next[int(ch - 'a')]) { 
                node->next[int(ch - 'a')] = new TreeNode26(ch); 
            }
            node = node->next[int(ch - 'a')];
            node->val = ch;
        }
        node->isLast = true;
    }
    /** Returns if the word is in the trie. */
    bool search(string word) {
        int size = word.size();
        TreeNode26 * node = root;
        char ch;
        for (int i = 1; i <= size; i++) {
            ch = word[i - 1];
            if (node->next[int(ch - 'a')]) {
                node = node->next[int(ch - 'a')];
            }
            else return false;
        }
        return node->isLast;
    }
    /** Returns if there is any word in the trie that starts with the given prefix. */
    bool startsWith(string prefix) {
        int size = prefix.size();
        TreeNode26 * node = root;
        char ch;
        for (int i = 1; i <= size; i++) {
            ch = prefix[i - 1];
            if (node->next[int(ch - 'a')]) {
                node = node->next[int(ch - 'a')];
            }
            else return false;
        }
        return true;
    }

};

 

相关文章: