实现一个带有buildDict, 以及 search方法的魔法字典。
对于buildDict方法,你将被给定一串不重复的单词来构建一个字典。
对于search方法,你将被给定一个单词,并且判定能否只将这个单词中一个字母换成另一个字母,使得所形成的新单词存在于你构建的字典中。
示例 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
注意:
你可以假设所有输入都是小写字母 a-z。
为了便于竞赛,测试所用的数据量很小。你可以在竞赛结束后,考虑更高效的算法。
请记住重置MagicDictionary类中声明的类变量,因为静态/类变量会在多个测试用例中保留。 请参阅这里了解更多详情。
思路:方法一:暴力求汉明距离
class MagicDictionary {
List<String> list;
/** Initialize your data structure here. */
public MagicDictionary() {
list=new ArrayList<>();
}
/** Build a dictionary through a list of words */
public void buildDict(String[] dict) {
for(int i=0;i<dict.length;i++)
list.add(dict[i]);
}
/** Returns if there is any word in the trie that equals to the given word after modifying exactly one character */
public boolean search(String word) {
for(int i=0;i<list.size();i++) {
int d=0;
if(word.length()!=list.get(i).length())
continue;
for(int j=0;j<word.length();j++) {
if(word.charAt(j)!=list.get(i).charAt(j))
d++;
if(d>1) break;
}
if(d==1) return true;
}
return false;
}
}
方法二:广义邻居。
回想一下,在方法 1 中,如果一个单词中只有一个字符可以更改以使字符串相等,那么两个单词就是邻居。
让我们假设一个词 “apple” 具有广义邻居 “pple”、“aple”、“aple”、“appe” 和 “appl”。在搜索像 apply 这样的词是否有像 apple 这样的邻居时,我们只需要知道它们是否有一个广义邻居。
继续上述思考,一个问题是 “apply” 不是自身的邻居,而是具有相同的广义邻居 “*pply”。为了解决这个问题,我们将计算生成 “*pply” 的源的数量。如果有 2 个或更多,则其中一个不会是 “apply”。如果只有一个,我们应该检查它不是 “apply”。无论是哪种情况,我们都可以确定有一些神奇的单词生成了 “*pply”,而不是 “apply”。
class MagicDictionary {
Set<String> st;
Map<String,Integer> map;
/** Initialize your data structure here. */
public MagicDictionary() {
st=new HashSet<>();
map=new HashMap<>();
}
public ArrayList<String> generalizedNeighbors(String word){
ArrayList<String> ans=new ArrayList<>();
char[] ca=word.toCharArray();
for(int i=0;i<word.length();i++) {
char letter=ca[i];
ca[i]='*';
String magic=new String(ca);
ans.add(magic);
ca[i]=letter;
}
return ans;
}
/** Build a dictionary through a list of words */
public void buildDict(String[] dict) {
for(String word : dict) {
st.add(word);
for(String nei : generalizedNeighbors(word)) {
map.put(nei, map.getOrDefault(nei, 0)+1);
}
}
}
/** Returns if there is any word in the trie that equals to the given word after modifying exactly one character */
public boolean search(String word) {
for(String nei : generalizedNeighbors(word)) {
int c=map.getOrDefault(nei, 0);
if(c>1 || c==1 && !st.contains(word)) return true;
}
return false;
}
}