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.
思路2:把word根据length收集起来,然后只考虑同一个length的string,如果diff == 1 return true。
T:(n * length(word));
class MagicDictionary {
/** Initialize your data structure here. */
HashMap<Integer, List<String>> lengthwords;
public MagicDictionary() {
this.lengthwords = new HashMap<>();
}
public void buildDict(String[] dictionary) {
if(dictionary == null || dictionary.length == 0) {
return;
}
for(String word: dictionary) {
int len = word.length();
lengthwords.putIfAbsent(len, new ArrayList<>());
lengthwords.get(len).add(word);
}
}
public boolean search(String searchWord) {
if(searchWord == null || searchWord.length() == 0) {
return false;
}
int len = searchWord.length();
if(lengthwords.get(len) != null) {
for(String candidate: lengthwords.get(len)) {
int diff = 0;
for(int i = 0; i < len; i++) {
if(candidate.charAt(i) != searchWord.charAt(i)) {
diff++;
}
}
if(diff == 1) {
return true;
}
}
}
return false;
}
}
/**
* Your MagicDictionary object will be instantiated and called as such:
* MagicDictionary obj = new MagicDictionary();
* obj.buildDict(dictionary);
* boolean param_2 = obj.search(searchWord);
*/
思路:这题就是trie的题目,核心考点就是把只变换一个char,转换成每个位子变一次,然后形成一个新的string,去trie里面搜,如果能搜到,那么就是好的,是个backtracking 和 trie的结合体,这个题目不错;
class MagicDictionary {
private class TrieNode {
public TrieNode[] children;
public boolean isword;
public String word;
public TrieNode() {
this.children = new TrieNode[26];
this.isword = false;
this.word = null;
}
}
private class Trie {
TrieNode root;
public Trie() {
root = new TrieNode();
}
public void insert(String word) {
TrieNode cur = root;
for(int i = 0; i < word.length(); i++) {
char c = word.charAt(i);
if(cur.children[c - 'a'] == null) {
cur.children[c - 'a'] = new TrieNode();
}
cur = cur.children[c - 'a'];
}
cur.isword = true;
cur.word = word;
}
}
private Trie trie;
/** Initialize your data structure here. */
public MagicDictionary() {
trie = new Trie();
}
/** Build a dictionary through a list of words */
public void buildDict(String[] dict) {
for(String word: dict) {
trie.insert(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) {
char[] ss = word.toCharArray();
TrieNode cur = trie.root;
for(int i = 0; i < ss.length; i++) {
for(char c = 'a'; c <= 'z'; c++) {
if(c == ss[i]) {
continue;
}
char origin = ss[i];
ss[i] = c;
if(canfind(new String(ss), trie.root)) {
return true;
}
ss[i] = origin;
}
}
return false;
}
private boolean canfind(String word, TrieNode root) {
TrieNode cur = root;
for(int i = 0; i < word.length(); i++) {
char c = word.charAt(i);
if(cur.children[c - 'a'] == null) {
return false;
}
cur = cur.children[c - 'a'];
}
return cur.isword;
}
}
/**
* Your MagicDictionary object will be instantiated and called as such:
* MagicDictionary obj = new MagicDictionary();
* obj.buildDict(dict);
* boolean param_2 = obj.search(word);
*/