676. Implement Magic Dictionary
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: 1. You may assume that all the inputs are consist of lowercase letters a-z. 2. For contest purpose, the test data is rather small by now. You could think about highly efficient algorithm after the contest. 3. 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. Todo : compare trade off Solution 1: Use trie Idea: build trie first and then do search , record the number of different chars , if the number of different chars > 1, return false already, If the number of different chars == 0 at the end , when it’s a word , return false If the number of different chars = 1 at the end of the word, return true // other’s code Below is my accepted java code. First build a trie tree, and in search(String word) function, we just edit every character from 'a' to 'z' and search the new string. (This process is like "word ladder") class MagicDictionary { class TrieNode { TrieNode[] children = new TrieNode[26]; boolean isWord; public TrieNode() {} } TrieNode root; /** Initialize your data structure here. */ public MagicDictionary() { root = new TrieNode(); } /** Build a dictionary through a list of words */ public void buildDict(String[] dict) { for (String s : dict) { TrieNode node = root; for (char c : s.toCharArray()) { if (node.children[c - 'a'] == null) { node.children[c - 'a'] = new TrieNode(); } node = node.children[c - 'a']; } node.isWord = true; } } /** 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[] arr = word.toCharArray(); for (int i = 0; i < word.length(); i++) { for (char c = 'a'; c <= 'z'; c++) { if (arr[i] == c) { continue; } char org = arr[i]; arr[i] = c; if (helper(new String(arr), root)) { return true; } arr[i] = org; } } return false; } public boolean helper(String s, TrieNode root) { TrieNode node = root; for (char c : s.toCharArray()) { if (node.children[c - 'a'] == null) { return false; } node = node.children[c - 'a']; } return node.isWord; } } Solution 2 : bucket by length Use. A HashMap to store key : length of a word , value: the words of the length When check if a word A is one char from the word in the HashMap, first get the list of words Sharing the same length , and then check one by one at each chars, if the number of different chats == 1 , return true, else return false class MagicDictionary { HashMap<Integer, List<String>> map; /** Initialize your data structure here. */ public MagicDictionary() { map = new HashMap(); } /** Build a dictionary through a list of words */ public void buildDict(String[] dict) { for(String word : dict){ if(!map.containsKey(word.length())){ map.put(word.length(), new ArrayList<>()); } map.get(word.length()).add(word); // buckets.computeIfAbsent(word.length(), x -> new ArrayList()).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) { if(!map.containsKey(word.length())) return false; for(String candidate : map.get(word.length())){ int mismatch = 0; for(int i = 0; i < word.length(); i++){ if(word.charAt(i) != candidate.charAt(i)) mismatch++; if(mismatch > 1) break; } if(mismatch == 1) return true; } return false; } }
posted on 2018-11-06 10:09 猪猪🐷 阅读(132) 评论(0) 收藏 举报
浙公网安备 33010602011771号