题目:
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
class MagicDictionary {
//给定单词字典数组,和需要对比的单词,魔术数组的含义是:对比单词中只需要更改一个字符即可在字典数组中找到相同的单词
//思路:采用对字典中的每个单词每个字母建立映射关系Map(剩下字母,当前字母映射集合)
//匹配:当前字母不同,剩下的字符串匹配成功,即返回true
//定义全局变量
HashMap<String,List<int[]>> hm=new HashMap<String,List<int[]>>();
/** Initialize your data structure here. */
public MagicDictionary() {
}
/** Build a dictionary through a list of words */
public void buildDict(String[] dict) {
//对词典中的每个单词进行切分处理
for(String word:dict){
for(int i=0;i<word.length();i++){
//将当前字母和剩下的字符串切开
String key=word.substring(0,i)+word.substring(i+1);
//将当前字母存入数组
int [] pair=new int[]{i,word.charAt(i)};
//获得映射数组的集合
List<int []> val=hm.getOrDefault(key,new ArrayList<int []>());
//将当前字母下标数组添加进集合
val.add(pair);
//存入Map
hm.put(key,val);
}
}
}
/** 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) {
//对单词进行切分匹配,只要剩下的相同,当前字母不同,即返回true
for(int i=0;i<word.length();i++){
String key=word.substring(0,i)+word.substring(i+1);
//如果存在相同的剩下字母串,则进行单个字母匹配,不同则true
if(hm.containsKey(key)){
//取出没有映射关系数组集合
for(int [] pair:hm.get(key)){
//位置相同,且字符不同
if(pair[0]==i&&pair[1]!=word.charAt(i)){
return true;
}
}
}
}
return false;
}
}
/**
* Your MagicDictionary object will be instantiated and called as such:
* MagicDictionary obj = new MagicDictionary();
* obj.buildDict(dict);
* boolean param_2 = obj.search(word);
*/
分析2(List集合实现--运行时间比分析1快):
class MagicDictionary {
//给定单词字典数组,和需要对比的单词,魔术数组的含义是:对比单词中只需要更改一个字符即可在字典数组中找到相同的单词
//思路:将字典添加进行List集合(不存在重复的,直接使用list),之后对每个匹配单词进行匹配。如果只有一个不同且长度相同,则返回true,否则返回false。
//分析:对字典数量小的适合,一旦字典数量大,时间复杂度显著下降
List<String> dics;
/** Initialize your data structure here. */
public MagicDictionary() {
dics=new ArrayList<String>();
}
/** Build a dictionary through a list of words */
public void buildDict(String[] dict) {
//将字典添加进集合
for(String word:dict){
dics.add(word);
}
}
/** 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 dic:dics){
//如果长度不匹配,直接进行下一个查找
if(word.length()!=dic.length()){
continue;
}else{
//长度相同
int diff=0,i=0;
for(i=0;i<word.length();i++){
//查找不同的数量,如果不同大于1,则直接判别下一个
if(dic.charAt(i)!=word.charAt(i)){
diff++;
if(diff>1){
break;
}
}
}
if(i==word.length()&&diff==1){
//说明匹配完成,只有一个不同
return true;
}
}
}
return false;
}
}
/**
* Your MagicDictionary object will be instantiated and called as such:
* MagicDictionary obj = new MagicDictionary();
* obj.buildDict(dict);
* boolean param_2 = obj.search(word);
*/
分析3(原创--较分析1和分析2更快):
class MagicDictionary {
//给定单词字典数组,和需要对比的单词,魔术数组的含义是:对比单词中只需要更改一个字符即可在字典数组中找到相同的单词
//思路:由题意可知,只有一个字母不同,长度相同,所有使用Map存储数组长度相同作为key(类似字典的索引),使用List集合作为value,然后在list中查找是否只有一个不同的字母
HashMap<Integer,List<String>> hm;
/** Initialize your data structure here. */
public MagicDictionary() {
//初始化全局变量
hm=new HashMap<Integer,List<String>>();
}
/** Build a dictionary through a list of words */
public void buildDict(String[] dict) {
//将字母长度相同的划分在一起
for(String word:dict){
int key=word.length();
//初始化list集合
List<String> list=hm.getOrDefault(key,new ArrayList<String>());
list.add(word);
hm.put(key,list);
}
}
/** 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) {
//查找相同长度的部分,如果不存在则直接返回
if(!hm.containsKey(word.length())){
return false;
}else{
//说明包含相同长度的,则在该list中查找
for(String s:hm.get(word.length())){
int diff=0,i=0;
for(i=0;i<word.length();i++){
if(s.charAt(i)!=word.charAt(i)){
diff++;
if(diff>1){
break;
}
}
}
//顺利匹配成功,只有一个不同的
if(i==word.length()&&diff==1){
return true;
}
}
}
return false;
}
}
/**
* Your MagicDictionary object will be instantiated and called as such:
* MagicDictionary obj = new MagicDictionary();
* obj.buildDict(dict);
* boolean param_2 = obj.search(word);
*/