LeetCode 211: 添加与搜索单词 - 数据结构设计

这篇博客介绍了如何使用前缀树解决LeetCode 211题,即添加与搜索单词的数据结构设计。文章详细讲解了如何实现WordDictionary类,包括addWord方法和search方法。search方法特别处理了单词中可能出现的'.'字符,该字符可以匹配任意字母。解题思路涉及两种搜索策略:基于层序遍历和基于迭代的搜索,以应对包含'.'的字符串匹配问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

LeetCode 211: 添加与搜索单词 - 数据结构设计

题目描述

如果数据结构中有任何与word匹配的字符串,则bool search(word)返回true,否则返回false。 单词可能包含点“。” 点可以与任何字母匹配的地方。

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

实现词典类 WordDictionary :

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

示例:

输入:
[“WordDictionary”,“addWord”,“addWord”,“addWord”,“search”,“search”,“search”,“search”]
[[],[“bad”],[“dad”],[“mad”],[“pad”],[“bad”],[".ad"],[“b…”]]
输出:
[null,null,null,null,false,true,true,true]

解释:
WordDictionary wordDictionary = new WordDictionary();
wordDictionary.addWord(“bad”);
wordDictionary.addWord(“dad”);
wordDictionary.addWord(“mad”);
wordDictionary.search(“pad”); // return False
wordDictionary.search(“bad”); // return True
wordDictionary.search(".ad"); // return True
wordDictionary.search(“b…”); // return True

提示:

1 <= word.length <= 500
addWord 中的 word 由小写英文字母组成
search 中的 word 由 ‘.’ 或小写英文字母组成
最调用多 50000 次 addWord 和 search

解题

    这里同样是考验二叉树的应用实例,如果不考虑单词中有‘.’的话,只需要借助哈希表就可以轻松完成添加和查找的功能,对于存在‘.’且可以表示任何一个字母时,枚举当前字符表达所对应的所有纯字母字符串再进行查找将会变得复杂,而前缀树可以简化操作。这里,构造一个前缀树和增加函数比较简单,最复杂的地方是查找函数,尤其是针对包含‘.’的字符的查找。当前字符为‘.’时,对应的备选项有多种,我们可以采用层序遍历的方式来同时进行多条备选的匹配,也可以通过迭代的方式遍历所有可匹配路径,其本质是N叉树的遍历。

基于层序遍历的搜索
class WordDictionary {
public:
    /** Initialize your data structure here. */
    WordDictionary() {
        root = new nNode;
    }
    
    /** Adds a word into the data structure. */
    void addWord(string word) {
        nNode *cur_node = root;
        for (auto s : word){
            if (cur_node->childs[s-'a'] == NULL)
                cur_node->childs[s-'a'] = new nNode;
            cur_node = cur_node->childs[s-'a'];
        }
        cur_node->is_word = true;
    }
    
    /** Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. */
    bool search(string word) {
        queue<nNode *>nNodes;
        nNode *cur_node;
        nNodes.push(root);
        for (auto s : word){
            if (nNodes.empty()) return false;
            int cur_size = nNodes.size();
            for (int i=0; i<cur_size; ++i){
                cur_node = nNodes.front();
                nNodes.pop();
                if (s == '.'){
                    for (int j=0; j<26; ++j){
                        if (cur_node->childs[j])
                            nNodes.push(cur_node->childs[j]);
                    }
                }
                else{
                    if (cur_node->childs[s-'a'])
                        nNodes.push(cur_node->childs[s-'a']);
                }
            }
        }
        while(!nNodes.empty()){
            if (nNodes.front()->is_word) return true;
            nNodes.pop();
        }
        return false;
    }

private:
    struct nNode{
        nNode *childs[26] = {NULL};  
        bool is_word = false;
    }*root;
};

/**
 * Your WordDictionary object will be instantiated and called as such:
 * WordDictionary* obj = new WordDictionary();
 * obj->addWord(word);
 * bool param_2 = obj->search(word);
 */
基于迭代的搜索
class WordDictionary {
public:
    /** Initialize your data structure here. */
    WordDictionary() {
        root = new nNode;
    }
    
    /** Adds a word into the data structure. */
    void addWord(string word) {
        nNode *cur_node = root;
        for (auto s : word){
            if (cur_node->childs[s-'a'] == NULL)
                cur_node->childs[s-'a'] = new nNode;
            cur_node = cur_node->childs[s-'a'];
        }
        cur_node->is_word = true;
    }
    
    /** Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. */
    bool search(string word) {
        return search(root, word, 0);
    }

private:
    struct nNode{
        nNode *childs[26] = {NULL};  
        bool is_word = false;
    }*root;

    bool search(nNode *root, string &word, int i){
        if (i == word.size()) return root->is_word;
        if (isalpha(word[i])){
            nNode *cur_node = root->childs[word[i]-'a'];
            return cur_node && search(cur_node, word, i+1);
        }
        else{
            for (int n=0; n < 26; ++n){
                if (root->childs[n] && search(root->childs[n], word, i+1)) return true;
            }
            return false;
        }
        return false;
    }
};

/**
 * Your WordDictionary object will be instantiated and called as such:
 * WordDictionary* obj = new WordDictionary();
 * obj->addWord(word);
 * bool param_2 = obj->search(word);
 */
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值