题目:
Implement a magic directory with buildDict
, and search
methods.
For the method buildDict
, you'll be given a list of non-repetitive words to build a dictionary.
For the method search
, you'll be given a word, and judge whether if you modify exactly one character into another character in this word, the modified word is in the dictionary you just built.
Example 1:
Input: buildDict(["hello", "leetcode"]), Output: Null Input: search("hello"), Output: False Input: search("hhllo"), Output: True Input: search("hell"), Output: False Input: search("leetcoded"), Output: False
Note:
- You may assume that all the inputs are consist of lowercase letters
a-z
. - For contest purpose, the test data is rather small by now. You could think about highly efficient algorithm after the contest.
- Please remember to RESET your class variables declared in class MagicDictionary, as static/class variables are persisted across multiple test cases. Please see here for more details.
分析:
实现一个带有buildDict, 以及 search方法的魔法字典。
对于buildDict方法,你将被给定一串不重复的单词来构建一个字典。
对于search方法,你将被给定一个单词,并且判定能否只将这个单词中一个字母换成另一个字母,使得所形成的新单词存在于你构建的字典中。
最先想到的是将每一个单词的每一个字母用另外的25个字母来替换,并放进set中,最后再在set中查询单词便可。
我们来看另一个有趣的解法。
对于一个单词,我们可以将每个字母用*号来代替存进map中,其对应的值则是替换的字母的集合,例如hello在map中存有:
*ello -> {h}
h*llo -> {e}
he*lo -> {l}
hel*o -> {l}
hell* -> {o}
当我们查询一个单词是否在魔法字典中,也将单词的每个字母用*号来替换,如果map中存在,且替换的字母不在对应set中,意味着能够查询到。
例:查询pello是否在字典中,先替换为(*ello,p),字典中有*ello,且p不在{h}中,我们应该返回true。
查询hello是否在字典中,先替换为(*ello,h),字典中有*ello,且h在{h}中,应该返回false。
如果我们将hello,pello存进字典中,再查询pello会是什么情况呢?
此时的字典中*ello->{h,p},若此时查询pello,因为p在{h,p}中,会返回false,可实际上应该要返回true的,所以我们还要加一个条件,就是或者当set中的元素大于一个的时候,意味着,*ello中的*可以替换为26个字母中的任意一个了,因为原来的hello无法通过修改一个字母来对应到hello,但有了pello的加入,hello可以通过替换第一个字母来对应到pello上。
此题还可以通过字典树来实现(后续补充)。
程序:
C++
class MagicDictionary { public: /** Initialize your data structure here. */ MagicDictionary() { mydict.clear(); } /** Build a dictionary through a list of words */ void buildDict(vector<string> dict) { for(string word:dict){ for(int i = 0; i < word.length(); ++i){ char c = word[i]; word[i] = '*'; mydict[word].insert(c); word[i] = c; } } } /** Returns if there is any word in the trie that equals to the given word after modifying exactly one character */ bool search(string word) { for(int i = 0; i < word.length(); ++i){ char c = word[i]; word[i] = '*'; if(mydict.count(word)){ if (!mydict[word].count(c) || mydict[word].size() > 1) return true; } word[i] = c; } return false; } private: unordered_map<string, unordered_set<char>> mydict; }; /** * Your MagicDictionary object will be instantiated and called as such: * MagicDictionary* obj = new MagicDictionary(); * obj->buildDict(dict); * bool param_2 = obj->search(word); */
Java