211. Design Add and Search Words Data Structure
MediumLeetCodeDesign a data structure that supports adding new words and finding if a string matches any previously added string.
Implement the WordDictionary
class:
WordDictionary()
Initializes the object.void addWord(word)
Adds word to the data structure, it can be matched later.bool search(word)
Returns true if there is any string in the data structure that matches word or false otherwise. word may contain dots '.' where dots can be matched with any letter.
Example
Input: ["WordDictionary","addWord","addWord","addWord","search","search","search","search"] [[],["bad"],["dad"],["mad"],["pad"],["bad"],[".ad"],["b.."]]
Output: [null,null,null,null,false,true,true,true]
Explanation: 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
Constraints
1 <= word.length <= 25
word
in addWord consists of lowercase English letters.word
in search consist of '.' or lowercase English letters.- There will be at most 2 dots in word for search queries.
- At most 10^4 calls will be made to addWord and search.
How to solve the problem
- Set (Time Limit Exceeded)
- Trie (Recommended)
python
# Approach 1: Set
class WordDictionary:
def __init__(self):
self.word_set = set()
def addWord(self, word: str) -> None:
self.word_set.add(word)
def search(self, word: str) -> bool:
for w in self.word_set:
if len(w) != len(word):
continue
for a, b in zip(w, word):
if b != "." and a != b:
break
else:
# for loop not break means all characters matched
return True
return False
python
# Approach 2: Trie
class TrieNode:
def __init__(self):
self.children = {} # Mapping from character to TrieNode
self.is_end = False # Indicates if a word ends here
class WordDictionary:
def __init__(self):
self.root = TrieNode()
def addWord(self, word: str) -> None:
node = self.root
for c in word:
if c not in node.children:
node.children[c] = TrieNode()
node = node.children[c]
node.is_end = True # Mark the end of a word
def search(self, word: str) -> bool:
def dfs(node, i):
if i == len(word):
# If we've reached the end of the word, check if it's a valid word
return node.is_end
c = word[i]
if c == ".":
# If the current character is '.', try all possible child nodes
for child in node.children.values():
if dfs(child, i + 1):
return True
return False
else:
# If the current character exists, continue the search
if c not in node.children:
return False
return dfs(node.children[c], i + 1)
return dfs(self.root, 0)
Complexity
- Approach 1 (Set): Time complexity: O(N * L), Space complexity: O(N * L)
- Approach 2 (Trie): Time complexity: O(L^2), Space complexity: O(N * L)
Comments
No comments yet. Be the first to comment!