LeetCode 实现一个魔法字典(前缀树)

实现一个带有buildDict, 以及 search方法的魔法字典。

对于buildDict方法,你将被给定一串不重复的单词来构建一个字典。

对于search方法,你将被给定一个单词,并且判定能否只将这个单词中一个字母换成另一个字母,使得所形成的新单词存在于你构建的字典中。

示例 1:

Input: buildDict(["hello", "leetcode"]), Output: Null
Input: search("hello"), Output: False
Input: search("hhllo"), Output: True
Input: search("hell"), Output: False
Input: search("leetcoded"), Output: False

注意:

你可以假设所有输入都是小写字母 a-z。
为了便于竞赛,测试所用的数据量很小。你可以在竞赛结束后,考虑更高效的算法。
请记住重置MagicDictionary类中声明的类变量,因为静态/类变量会在多个测试用例中保留。 请参阅这里了解更多详情。

思路分析: 涉及到在字典中搜索单词的问题,一般前缀树的的结构能高效的解决问题。此题也是在单词组中搜索单词,蛋试需要搜索与word相差一个字母的单词,就是难度稍微增大了一点点。
关于前缀树的数据结构以及应用,请翻阅 LeetCode 前缀树及其运用

//前缀树的程序表示
class TrieNode {
public:
    bool isWord;//当前节点为结尾是否是字符串
    vector<TrieNode*> children;
    TrieNode() : isWord(false), children(26, nullptr) {}
    ~TrieNode() {
        for (TrieNode* child : children)
            if (child) delete child;
    }
};

class MagicDictionary {
private:
    TrieNode *trieRoot;//构建的单词后缀树
    //在树中插入一个单词的方法实现
    void addWord(string &word) {
        TrieNode *ptr = trieRoot;//扫描这棵树,将word插入
        //将word的字符逐个插入
        for (auto ch : word) {
            if (ptr->children[ch - 'a'] == NULL) {
                ptr->children[ch - 'a'] = new TrieNode();
            }
            ptr = ptr->children[ch - 'a'];
        }
        ptr->isWord = true;//标记为单词
    }
    //在nowTreePtr中搜索word[index],isMod代表的是是否使用了替换一个字母的机会
    bool myFindWord(TrieNode *nowTreePtr, string &word, int index, bool isMod){
        if (nowTreePtr == NULL){
            return false;
        }
        if (word.size() == index){
            //此时搜索完毕,必须保证nowTreePtr也到达了一个单词的尾端,并且替换一个字母的机会也使用了
            return isMod && nowTreePtr->isWord;
        }
        else{
            //搜索nowTreePtr的26个节点
            for (int i = 0; i < 26; ++i){
                if (nowTreePtr->children[i] != NULL){
                    if ('a' + i == word[index]){
                        //成功匹配,继续搜索下一个字母
                        if (myFindWord(nowTreePtr->children[i], word, index + 1, isMod)){
                            return true;
                        }
                    }
                    else if (isMod == false && myFindWord(nowTreePtr->children[i], word, index + 1, true)){
                        //如果'a' + i != word[index],则使用替换字母的机会(在此之前替换字母的机会是没有使用的,因为只能使用一次)
                        return true;
                    }
                }
            }
            return false;
        }
    }
public:
    /** Initialize your data structure here. */
    MagicDictionary() {
        trieRoot = new TrieNode();
    }

    /** Build a dictionary through a list of words */
    void buildDict(vector<string> dict) {
        //构建字典树
        for (auto &word : dict){
            addWord(word);
        }
    }

    /** Returns if there is any word in the trie that equals to the given word after modifying exactly one character */
    bool search(string word) {
        return myFindWord(trieRoot, word, 0, false);
    }
};

/**
 * Your MagicDictionary object will be instantiated and called as such:
 * MagicDictionary* obj = new MagicDictionary();
 * obj->buildDict(dict);
 * bool param_2 = obj->search(word);
 */

在这里插入图片描述

©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页