[LeetCode]Add and Search Word - Data structure design

来源:互联网 发布:好听的歌 知乎 编辑:程序博客网 时间:2024/06/05 22:07
字典树( Trie )
推荐一个对字典树解释的很好的博客 Trie树:应用于统计和排序 

解题思路:
阅读完题目,大家都知道是字典树。对于树的搜索算法有 深度优先搜索算法(dfs)和宽度优先搜索算法(bfs)。针对题目的描述,只要能找到一个匹配的,即可返回true。所以,采用dfs,深度挖掘有用信息,只要发现pattern匹配,就结束搜索。(bfs在这里会产生很多冗余的搜索,浪费时间)

对于DFS算法,其递归实现简单且容易理解。下面就描述一下其条件

首先看一下TrieNode的数据结构 
static const int NUM_CHARS = 26;    struct TrieNode{        int freq;            //词频统计,该题目中并没有用到        bool isWord;     //是否是一个word的结束位置        char nodechar; // 该节点字符,该题目没有用到        vector<TrieNode*> child;        TrieNode():freq(0),                 nodechar(0),                 isWord(false),                child(vector<TrieNode*>(26, nullptr)){ // 一定要对vector初始化,初始化为nullptr,否则RE        }    };

对于search方法,其使用dfs实现pattern的匹配
边界条件:
1,node == NULL; 说明其上一个dfs调用查找的char不存在于dictionary中,返回false
2,ch == ‘\0’, 字符串查找结束,当前node不为NULL,那么他的 isWord 标记可表示这个word是否存在
3,ch == ‘.’ 与否,分两种情况进行递归搜索

对于addWord方法:
前条件:location = root;
不变式:如果location->child[ch-‘a’] == NULL , new一个,location = location->child[ch-‘a’];
结束条件:word遍历完;
边界条件:word是空的 

class WordDictionary {public:    TrieNode * root;    WordDictionary(): root(new TrieNode){}    // Adds a word into the data structure.    void addWord(string word) {          if(word.length() == 0) return;        TrieNode* location = root;        for (int i = 0; i < word.length(); ++i){            int index = word[i] - 'a';            if (location->child[index] == NULL){                location->child[index] = new TrieNode();            }            location = location->child[index];            location->nodechar = word[i];        }        location->freq += 1;        location->isWord = 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 dfs(word.c_str(), root);    }     // 字符串的遍历,用string.c_str()来作为参数,真的很精彩    bool dfs(const char *ch, TrieNode* cur){        if (cur == NULL) return false;        if (*ch == '\0') return cur->isWord;        if (*ch == '.'){            for (int i = 0; i < NUM_CHARS; ++i){                if (cur->child[i] != NULL){                    if (dfs(ch+1, cur->child[i]))                        return true;                }            }        }else{            return dfs(ch+1, cur->child[*ch-'a']);        }    }};// Your WordDictionary object will be instantiated and called as such:// WordDictionary wordDictionary;// wordDictionary.addWord("word");// wordDictionary.search("pattern");


0 0