题目链接
题目描述
设计一个使用单词列表进行初始化的数据结构,单词列表中的单词 互不相同 。 如果给出一个单词,请判定能否只将这个单词中一个字母换成另一个字母,使得所形成的新单词存在于已构建的神奇字典中。
实现 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:该邻居单词没有在字典中找到邻居单词,需要判断下一个邻居单词。
代码
Python
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
Go
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
}