Design a data structure that is initialized with a list of different words. Given a string, 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 strings dictionary
.bool search(String searchWord)
Returns true
if you can change exactly one character in searchWord
to match any string in the data structure; otherwise, returns false
.Example:
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
The naive solution involves iterating through the dictionary for each search word and comparing each word in the dictionary with the search word. For each comparison, we count the number of differing characters. If exactly one character differs, we return true
. Otherwise, we continue the search. If we reach the end of the dictionary without finding a match, we return false
.
class MagicDictionary:
def __init__(self):
self.dictionary = []
def buildDict(self, dictionary: List[str]) -> None:
self.dictionary = dictionary
def search(self, searchWord: str) -> bool:
for word in self.dictionary:
if len(word) == len(searchWord):
diff_count = 0
for i in range(len(word)):
if word[i] != searchWord[i]:
diff_count += 1
if diff_count == 1:
return True
return False
buildDict
: O(N), where N is the number of words in the input dictionary
.search
: O(M * L), where M is the number of words in the dictionary and L is the length of the search word.A slightly more optimal solution could involve using a hash map to store words grouped by their length. During the search, only words with the same length as the searchWord
need to be considered. This approach reduces the number of unnecessary comparisons.
class MagicDictionary:
def __init__(self):
self.length_map = {}
def buildDict(self, dictionary: List[str]) -> None:
for word in dictionary:
length = len(word)
if length not in self.length_map:
self.length_map[length] = []
self.length_map[length].append(word)
def search(self, searchWord: str) -> bool:
length = len(searchWord)
if length not in self.length_map:
return False
for word in self.length_map[length]:
diff_count = 0
for i in range(length):
if word[i] != searchWord[i]:
diff_count += 1
if diff_count == 1:
return True
return False
buildDict
: O(N), where N is the number of words in the input dictionary
.search
: O(K * L), where K is the number of words with the same length as the search word, and L is the length of the search word. In the worst case, K can be equal to N, so it can still be O(N*L), but on average it's better if the word lengths are varied.length_map
.These edge cases are handled correctly in the provided implementations.