剑指 Offer II 064. 神奇的字典

题目链接

力扣

题目描述

设计一个使用单词列表进行初始化的数据结构,单词列表中的单词 互不相同 。 如果给出一个单词,请判定能否只将这个单词中一个字母换成另一个字母,使得所形成的新单词存在于已构建的神奇字典中。

实现 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
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值