【LeetCode75】第七十题 实现前缀树

目录

题目:

示例:

分析:

代码:


题目:

【LeetCode75】第七十题 实现前缀树_第1张图片

示例:

【LeetCode75】第七十题 实现前缀树_第2张图片

分析:

这是一道设计类的题目。要我们写出一个前缀树。那么我们首先需要知道什么是前缀树是什么才可以写出来。

以本题为例,本题需要存储的字符串只包含26个小写的英文字母,所以本题的前缀树实际上是一棵26叉树。

再以示例1为例,最终的前缀树实际上是这样的。

【LeetCode75】第七十题 实现前缀树_第3张图片

 虽然看起来像一个链表,但是它实际上是26叉树,只不过它的其他分支都是空子树,所以才是这个样子的。

那么我们可以发现这棵数有两个节点是颜色不一样的,这是什么含义呢,这就意味着存储在前缀树的字符串中有以这根节点开头,以这个节点结尾的字符串。也就是“app”和“apple”。

既然是26叉树,所以每个节点都有26个子节点,我们一般用数组来存放,并且要记录是否有字符串以本节点结尾,所以还需要有个标记,因此一个基础的前缀树的类应该是这样的:

class Node{
public:
    Node(){
        child=vector(26,nullptr);
        end=false;
    }
    vectorchild;
    bool end;
};

我们注意到这棵前缀树的节点没有值,只有子树数组和一个是否结尾的标记,那是因为我们本题中只需要判断是否有某字符串存储在内以及是否有某前缀在内,因此是可以省略的。

接下来我们来讲一下前缀树是怎么使用的,大家应该就明白为什么不需要存储节点的值了。

 【LeetCode75】第七十题 实现前缀树_第4张图片

 假设上图是我构造的一棵前缀树,节点的值仅仅是为了我们方便观察加上去的,实际上节点可以不需要存放值。

假设我去寻找前缀树中是否存放着“abc”这个字符串。

那么我们首先先去根节点寻找是否有存放‘a’,由于‘a’是26个字母中的第一个字母,并且我们每个节点的子树都是存放在一个长度为26的数组里。

因此我们只要看看子树数组的第一个位置是否为空节点即可知道是否有‘a’这个字母。接着我们在在‘a’这个节点再去寻找其子树数组的第二个位置找到‘b’,再在‘b’的子树数组的第三个位置找到‘c’。最后我们根据‘c’的节点的标记查看其是否是某个字符串的结尾即可。

那么再假设我要找的字符串是“ab”,那么当我们找到‘b’这个节点时我们看看这个节点的结尾标记,发现并不是某字符串的结尾,那么就说明前缀树里没有存放"ab"这个字符串。

和查找字符串不同的是,查找前缀不需要查看结尾的节点是否有结尾标记,因为只是前缀,所以能一路找到前缀的最后即可,不需要知道存放在前缀树里的这个字符串是不是一个完整的字符串。

那么知道前缀树怎么设计以及使用之后,本题就轻而易举了。具体的完整代码可以参考下面。

代码:

class Node{
public:
    Node(){
        child=vector(26,nullptr);
        end=false;
    }
    vectorchild;
    bool end;
};

class Trie {
public:
    Node* root;
    Trie() {
        root=new Node();
    }
    
    void insert(string word) {
        Node* node=root;
        for(char &c:word){
            int n=static_cast(c-'a');
            if(node->child[n]==nullptr){
                node->child[n]=new Node();
            }
            node=node->child[n];
        }
        node->end=true;
    }
    
    bool search(string word) {
        Node* node=root;
        for(char &c:word){
            int n=static_cast(c-'a');
            if(node->child[n]==nullptr) return false;
            node=node->child[n];
        }
        return node->end;
    }
    
    bool startsWith(string prefix) {
        Node* node=root;
        for(char &c:prefix){
            int n=static_cast(c-'a');
            if(node->child[n]==nullptr) return false;
            node=node->child[n];
        }
        return true;
    }
};

你可能感兴趣的:(LeetCode75题解,leetcode,算法,c++,数据结构)