leetcode-211. 添加与搜索单词 - 数据结构设计

leetcode-211. 添加与搜索单词 - 数据结构设计

题目:

请你设计一个数据结构,支持 添加新单词 和 查找字符串是否与任何先前添加的字符串匹配 。

实现词典类 WordDictionary :

  • WordDictionary() 初始化词典对象
  • void addWord(word) 将 word 添加到数据结构中,之后可以对它进行匹配
  • bool search(word) 如果数据结构中存在字符串与 word 匹配,则返回 true ;否则,返回 false 。word 中可能包含一些 '.' ,每个 . 都可以表示任何一个字母。

思路:

  • 本题直接将所有的单词存入数组中,在查找时遍历所有单词,但这样代码查找效率低下,可能会超时,因此我们可以对单词根据代码根据长度进行分类,存储到map<int,vector<string>>的数据结构中,map的key为长度,value为对应长度的单词,插入单词时先计算单词长度再插入对应的数组中,查找时,直接根据单词长度找到对应的集合,遍历集合中的所有单词,再进行逐字符匹配,如果是'.'则跳过该次,如果有单词匹配成功则返回true。

  • 本题也可以通过前缀树解决,因为单词只有26个,因此构建的字典树为26叉树,并置一个标志isEnd记录此字母是否为单词末尾

    数据结构:

    class TrieNode{
        public:
        //存储孩子节点
        vector<TrieNode*> child;
        //末尾标志
        bool isEnd;
        TrieNode(){
            //初始化孩子节点
            child=vector<TrieNode*>{26,nullptr};
            //默认置为false,插入时将最后一个字母的标志置为true
            isEnd=false;
        };
    };
    

    插入元素时,通过遍历将单词合并到前缀树

    查找元素时,

    • 如果遍历到单词末尾,则意味着单词匹配成功,返回true
    • 如果单当前字母为a-z,则递归判断trie->child[word[i]-'a']和word[i+1:]的查询结果
    • 如果遍历的当前字母为'.',则需要对每个子节点都进行一次递归查找

Code

  • map集合
class WordDictionary {
public:
    map<int,vector<string>> m;
    WordDictionary() {
        
    }
    
    void addWord(string word) {
        if(m.count(word.size())==0){
            vector<string> cur={word};
            m[word.size()]=cur;
        }
        else{
            m[word.size()].push_back(word);
        }
    }
    
    bool search(string word) {
        int len=word.size();
        if(m.count(len)==0){
            return false;
        }
        for(auto item:m[word.size()]){
            bool have=true;
            for(int i=0;i<len;i++){
                if(word[i]!='.' && word[i]!=item[i]){
                    have=false;
                }
            }
            if(have){
                return true;
            }
        }
        return false;
    }
};
  • 前缀树
class TrieNode{
    public:
    vector<TrieNode*> child;
    bool isEnd;
    TrieNode(){
        child=vector<TrieNode*>{26,nullptr};
        isEnd=false;
    };
};
class WordDictionary {
public:
    TrieNode* root;
    WordDictionary() {
        root=new TrieNode();
    }
    
    void addWord(string word) {
        TrieNode* cur=root;
        for(int i=0;i<word.size();i++){
            if(cur->child[word[i]-'a']==nullptr){
                cur->child[word[i]-'a']=new TrieNode();
            }
            cur=cur->child[word[i]-'a'];
        }
        //末尾标志置位true
        cur->isEnd=true;
    };
    
    bool search(string word) {
        TrieNode* cur=root;
        //递归查询
        return dfs(cur,0,word);
    };
    bool dfs(TrieNode* root,int inx,string word){
        //查找到末尾
        if(inx==word.size()){
            return root->isEnd;
        };
        //遇到'.'需要将26个字母都遍历一次
        if(word[inx]=='.'){
            for(int i=0;i<26;i++){
                if(root->child[i]!=nullptr && dfs(root->child[i],inx+1,word)){
                    return true;
                }
            }
            return false;
        }
        else{
            if(root->child[word[inx]-'a']!=nullptr && dfs(root->child[word[inx]-'a'],inx+1,word)){
                return true;
            }
            return false;
        };
    };
};
posted @ 2021-10-19 22:39  流光之中  阅读(56)  评论(0编辑  收藏  举报