设计一个使用单词列表进行初始化的数据结构,单词列表中的单词 互不相同 。 如果给出一个单词,请判定能否只将这个单词中一个字母换成另一个字母,使得所形成的新单词存在于已构建的神奇字典中。
实现 MagicDictionary 类:
MagicDictionary() 初始化对象
void buildDict(String[] dictionary) 使用字符串数组 dictionary 设定该数据结构,dictionary 中的字符串互不相同
bool search(String searchWord) 给定一个字符串 searchWord ,判定能否只将字符串中 一个 字母换成另一个字母,使得所形成的新字符串能够与字典中的任一字符串匹配。如果可以,返回 true ;否则,返回 false 。
示例:
输入
inputs = ["MagicDictionary", "buildDict", "search", "search", "search", "search"]
inputs = [[], [["hello", "leetcode"]], ["hello"], ["hhllo"], ["hell"], ["leetcoded"]]
输出
[null, null, false, true, false, false]解释
MagicDictionary magicDictionary = new MagicDictionary();
magicDictionary.buildDict(["hello", "leetcode"]);
magicDictionary.search("hello"); // 返回 False
magicDictionary.search("hhllo"); // 将第二个 'h' 替换为 'e' 可以匹配 "hello" ,所以返回 True
magicDictionary.search("hell"); // 返回 False
magicDictionary.search("leetcoded"); // 返回 False
提示:
1 <= dictionary.length <= 100
1 <= dictionary[i].length <= 100
dictionary[i] 仅由小写英文字母组成
dictionary 中的所有字符串 互不相同
1 <= searchWord.length <= 100
searchWord 仅由小写英文字母组成
buildDict 仅在 search 之前调用一次
最多调用 100 次 search
哈希表
首先定义一个概念邻居单词:如果两个单词只差一个字母则称为邻居单词,例如hello的邻居单词有*hllo,h*llo,he*lo,hel*o,hell*这些,*可以匹配任何字母
于是题目就可以变为判定查找单词是否在字典中存在邻居单词
在build过程中,对每个字典里的单词找到对应的所有邻居单词,并把邻居单词以键值对的方式存入哈希表,键为邻居单词,值为出现次数,这里的出现次数是对字典范围内所有单词而言,例如“hello”和“hallo”这两个单词都会有h*llo的邻居,因此哈希表中h*llo的值为2。
然后再查找过程中同样需要获取查找单词的所有邻居单词,并遍历所有邻居单词,如果邻居单词的哈希表次数:
大于1:说明字典里出现了互为邻居单词的多个单词,在这种情况下说明字典中不止一个单词是查找单词的邻居单词,可以返回true。
等于1:分两种情况,第一种情况是查找单词本身也在字典里,且字典里没有该单词的邻居单词,这种情况需要舍弃掉本次判断,直接continue;第二种情况是字典里有一个查找单词的邻居单词,可以返回true。
等于0:该邻居单词没有在字典中找到邻居单词,需要判断下一个邻居单词。
- class MagicDictionary:
-
- def __init__(self):
- """
- Initialize your data structure here.
- """
- self.hashMap = collections.defaultdict(int)
- self.wordSet = []
-
- def getNeighbor(self, word) -> list[str]:
- wordList = list(word)
- ans = []
- for i in range(len(word)):
- tmp = wordList[i]
- wordList[i] = '*'
- neighbor = ''.join(wordList)
- ans.append(neighbor)
- wordList[i] = tmp
- return ans
-
- def buildDict(self, dictionary: list[str]) -> None:
- for word in dictionary:
- self.wordSet.append(word)
- neighbors = self.getNeighbor(word)
- for neighbor in neighbors:
- self.hashMap[neighbor] += 1
- return
-
- def search(self, searchWord: str) -> bool:
- neighbors = self.getNeighbor(searchWord)
- for neighbor in neighbors:
- wordfreq = self.hashMap[neighbor]
- if wordfreq > 1:
- return True
- elif wordfreq == 1:
- if searchWord in self.wordSet:
- continue
- return True
- return False
- type Set []string
-
- func (s Set) have(str string) bool {
- for _, word := range s {
- if word == str {
- return true
- }
- }
- return false
- }
-
- func (s *Set) add(str string) {
- *s = append(*s, str)
- }
-
- type MagicDictionary struct {
- hashMap map[string]int
- set Set
- }
-
- /** Initialize your data structure here. */
- func Constructor() MagicDictionary {
- return MagicDictionary{
- hashMap: make(map[string]int), //这里注意需要初始化hashMap
- }
- }
-
- func getNeighbors(word string) []string {
- ans := []string{}
- for i := 0; i < len(word); i++ {
- ans = append(ans, word[:i]+"*"+word[i+1:])
- }
- return ans
- }
-
- func (this *MagicDictionary) BuildDict(dictionary []string) {
- for _, word := range dictionary {
- this.set.add(word)
- neighbors := getNeighbors(word)
- for _, neighbor := range neighbors {
- this.hashMap[neighbor] += 1
- }
- }
- return
- }
-
- func (this *MagicDictionary) Search(searchWord string) bool {
- neighbors := getNeighbors(searchWord)
- for _, neighbor := range neighbors {
- wordFreq := this.hashMap[neighbor]
- if wordFreq > 1 {
- return true
- } else {
- if wordFreq == 1 {
- if this.set.have(searchWord) {
- continue
- }
- return true
- }
- }
- }
- return false
- }