Design a data structure that is initialized with a list of different words. Provided a string, you should determine if you can change exactly one character in this string to match any word in the data structure.
Implement the MagicDictionary
class:
MagicDictionary()
Initializes the object.void buildDict(String[] dictionary)
Sets the data structure with an array of distinct stringsdictionary
.bool search(String searchWord)
Returnstrue
if you can change exactly one character insearchWord
to match any string in the data structure, otherwise returnsfalse
.
Example 1:
Input ["MagicDictionary", "buildDict", "search", "search", "search", "search"] [[], [["hello", "leetcode"]], ["hello"], ["hhllo"], ["hell"], ["leetcoded"]] Output [null, null, false, true, false, false] Explanation MagicDictionary magicDictionary = new MagicDictionary(); magicDictionary.buildDict(["hello", "leetcode"]); magicDictionary.search("hello"); // return False magicDictionary.search("hhllo"); // We can change the second 'h' to 'e' to match "hello" so we return True magicDictionary.search("hell"); // return False magicDictionary.search("leetcoded"); // return False
Constraints:
1 <= dictionary.length <= 100
1 <= dictionary[i].length <= 100
dictionary[i]
consists of only lower-case English letters.- All the strings in
dictionary
are distinct. 1 <= searchWord.length <= 100
searchWord
consists of only lower-case English letters.buildDict
will be called only once beforesearch
.- At most
100
calls will be made tosearch
.
又是一道典型的关于前缀树的题,还是LeetCode 208. Implement Trie (Prefix Tree) 的拓展。不同的地方是查找的条件不同,给定一个单词必须也只能修改其中一个字母为任意字母,问是否能在字典集里找到修改后的单词?
前缀树(Trie)数据结构定义和单词插入函数跟LeetCode 208. Implement Trie (Prefix Tree) 是一样的。
查找函数:根据单词的每一个字母沿着前缀树的根节点往下搜索。在处理每一个字母时,会有如下两种情况:
1)在这个字母之前没有改变过字母:需要判断当前节点的所有非空子节点,对于与当前字母匹配的节点表示仍然不用改变字母可以继续往后匹配搜索(之后还有一次改变机会);对于其它节点表示在这个节点改变了一次字母然后继续往后匹配搜索(之后没有改变机会,必须严格匹配直到最后)。
2)在这个字母之前已经改变过一次字母,那就查找严格匹配的子节点,如为空节点可以直接停止;如不为空则可以继续往后搜索。
按以上两种情况处理每个字母直到最后一个字母,最后一个节点需要判断是否为有效单词还需要判断之前是否有使用一次改变的机会。只有两个条件都满足才表示找到可以匹配的单词。
class TrieNode:
def __init__(self):
self.end = False
self.children = [None] * 26
class MagicDictionary:
def __init__(self):
self.root = TrieNode()
def buildDict(self, dictionary: List[str]) -> None:
for word in dictionary:
node = self.root
for c in word:
idx = ord(c) - ord('a')
if not node.children[idx]:
node.children[idx] = TrieNode()
node = node.children[idx]
node.end = True
def search(self, searchWord: str) -> bool:
def helper(word, node, flag): #flag表示是否改变一次字母
if not word:
return node.end and flag
for j in range(26):
child = node.children[j]
if not child:
continue
c = chr(ord('a') + j)
if c == word[0]:
if helper(word[1:], child, flag):
return True
else:
if flag == False:
if helper(word[1:], child, True):
return True
return False
return helper(searchWord, self.root, False)