[LeetCode] Add and Search Word - Data Structure Design

简介: This problem is an application of the Trie data structure. In the following, it is assumed that you have solved Implement Trie (Prefix Tree).

This problem is an application of the Trie data structure. In the following, it is assumed that you have solved Implement Trie (Prefix Tree).

Now, let's first look at the TrieNode class. I define it as follows.

1 class TrieNode {
2 public:
3     bool isKey;
4     TrieNode* children[26];
5     TrieNode(): isKey(false) {
6         memset(children, NULL, sizeof(TrieNode*) * 26); 
7     }
8 };

The field isKey is to label whether the string comprised of characters starting from root to the current node is a key (word that has been added). In this problem, only lower-case letters a - zneed to be considered, so each TrieNode has at most 26 children. I store it in an array ofTrieNode*children[i] corresponds to letter 'a' + i. The remaining code defines the constructor of the TrieNode class.

Adding a word can be done in the same way as in Implement Trie (Prefix Tree). The basic idea is to create a TrieNode corresponding to each letter in the word. When we are done, label the last node to be a key (set isKey = true). The code is as follows.

1 void addWord(string word) {
2     TrieNode* run = root;
3     for (char c : word) {
4         if (!(run -> children[c - 'a']))
5             run -> children[c - 'a'] = new TrieNode();
6         run = run -> children[c - 'a']; 
7     }
8     run -> isKey = true;
9 }

By the way, root is defined as private data of WordDictionary:

1 private:
2     TrieNode* root;

And the WordDictionary class has a constructor to initialize root:

1 WordDictionary() {
2     root = new TrieNode();
3 }

Now we are left only with search. Let's do it. The basic idea is still the same as typical search operations in a Trie. The critical part is how to deal with the dots .. Well, my solution is very naive in this place. Each time when we reach a ., just traverse all the children of the current node and recursively search the remaining substring in word starting from that children. So I define a helper function query for search that takes in a string and a starting node. And the initial call to query is like query(word, root).

By the way, I pass a char* instead of string to query and it greatly speeds up the code. So the initial call to query is actually query(word.c_str(), root).

Now I put all the codes together below. Hope it to be useful!

 1 class TrieNode {
 2 public:
 3     bool isKey;
 4     TrieNode* children[26];
 5     TrieNode(): isKey(false) {
 6         memset(children, NULL, sizeof(TrieNode*) * 26);
 7     }
 8 };
 9 
10 class WordDictionary {
11 public:
12     WordDictionary() {
13         root = new TrieNode();
14     }
15 
16     // Adds a word into the data structure.
17     void addWord(string word) {
18         TrieNode* run = root;
19         for (char c : word) {
20             if (!(run -> children[c - 'a'])) 
21                 run -> children[c - 'a'] = new TrieNode();
22             run = run -> children[c - 'a'];
23         }
24         run -> isKey = true;
25     }
26 
27     // Returns if the word is in the data structure. A word could
28     // contain the dot character '.' to represent any one letter.
29     bool search(string word) {
30         return query(word.c_str(), root);
31     }
32 
33 private:
34     TrieNode* root;
35 
36     bool query(const char* word, TrieNode* node) {
37         TrieNode* run = node;
38         for (int i = 0; word[i]; i++) {
39             if (run && word[i] != '.')
40                 run = run -> children[word[i] - 'a'];
41             else if (run && word[i] == '.') { 
42                 TrieNode* tmp = run;
43                 for (int j = 0; j < 26; j++) {
44                     run = tmp -> children[j];
45                     if (query(word + i + 1, run))
46                         return true;
47                 }
48             }
49             else break;
50         }
51         return run && run -> isKey; 
52     }
53 };
54 
55 // Your WordDictionary object will be instantiated and called as such:
56 // WordDictionary wordDictionary;
57 // wordDictionary.addWord("word");
58 // wordDictionary.search("pattern");

 

目录
相关文章
Leetcode 623. Add One Row to Tree
题目很简单,在树的第d层加一层,值为v。递归增加一层就好了。代码如下
47 0
|
存储 C++ Python
LeetCode刷题---Add Two Numbers(一)
LeetCode刷题---Add Two Numbers(一)
|
存储 算法 安全
LeetCode - #2 Add Two Numbers
我们社区从本期开始会将顾毅(Netflix 增长黑客,《iOS 面试之道》作者,ACE 职业健身教练。)的 Swift 算法题题解整理为文字版以方便大家学习与阅读。 不积跬步,无以至千里;不积小流,无以成江海,Swift社区 伴你前行。
LeetCode - #2 Add Two Numbers
LeetCode 415. Add Strings
给定两个字符串形式的非负整数 num1 和num2 ,计算它们的和。
95 0
LeetCode 415. Add Strings
LeetCode 318. Maximum Product of Word Lengths
给定一个字符串数组 words,找到 length(word[i]) * length(word[j]) 的最大值,并且这两个单词不含有公共字母。你可以认为每个单词只包含小写字母。如果不存在这样的两个单词,返回 0。
77 0
LeetCode 318. Maximum Product of Word Lengths
|
算法 Python
LeetCode 295. Find Median from Data Stream
中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。
103 0
LeetCode 295. Find Median from Data Stream
LeetCode 290. Word Pattern
给定一种 pattern(模式) 和一个字符串 str ,判断 str 是否遵循相同的模式。 这里的遵循指完全匹配,例如, pattern 里的每个字母和字符串 str 中的每个非空单词之间存在着双向连接的对应模式。
49 0
LeetCode 290. Word Pattern
LeetCode 258. Add Digits
给定一个非负整数 num,反复将各个位上的数字相加,直到结果为一位数。
70 0
LeetCode 258. Add Digits
LeetCode 241. Different Ways to Add Parentheses
给定一个含有数字和运算符的字符串,为表达式添加括号,改变其运算优先级以求出不同的结果。你需要给出所有可能的组合的结果。有效的运算符号包含 +, - 以及 * 。
81 0
LeetCode 241. Different Ways to Add Parentheses
LeetCode 212. Word Search II
给定一个二维网格 board 和一个字典中的单词列表 words,找出所有同时在二维网格和字典中出现的单词。 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。
79 0
LeetCode 212. Word Search II