leetcode 676. Implement Magic Dictionary | 676. 实现一个魔法字典(DFS+Trie 前缀树)
題目
https://leetcode.com/problems/implement-magic-dictionary/description/
題解
題意理解
前綴樹問題,大意是是讓你在字典中找到是否存在與當前字符串有 1 個字符的 diff 的匹配。參考了:leetcode 208. Implement Trie (Prefix Tree) | 208. 實現(xiàn) Trie 前綴樹(Java) 的代碼,并做了一些修改。
修改的時候,需要注意的細節(jié)比較多。比如從 [“hello”,“hallo”] 中查找 “hello” 時,應該返回 true,而從 [“hello”] 中查找 “hello” 時,應該返回 false。這就要求我們不能直接去匹配,而是需要故意去嘗試走不匹配的路徑。
整體思路
我們規(guī)定一種 tolerance 機制:將有一個字符匹配失敗的情況作為 fault,而這種 fault 是可以被容忍、且必須存在的,只有在遇到了 fault 之后,剩下的字符串才可以安心地進行 one-way 匹配。
遇到 fault 之后,我們將剩下的字符串進行經(jīng)典的 Trie search, 將查找的結(jié)果稱為 failover(形不形象?)。注:在代碼中,!tolerance 就是遇到過 fault 的意思。
正確性證明:在 searchPrefix 函數(shù)中,只有在 !tolerance,且成功匹配剩余所有字符的情況下,才會返回 failover 節(jié)點。所以最后只需要對 failover 進行判斷,如果 failover 非空并且 failover.isEnd 的話,說明成功的找到了一個包含 1 個 diff 字符的匹配。
代碼
時間復雜度比較難以計算,運行效率還不錯。
class Node {Node[] map;boolean isEnd;public Node() {this.map = new Node['z' - 'a' + 1];}public Node get(char c) {return map[c - 'a'];}public Node put(char c) {Node node = new Node();map[c - 'a'] = node;return node;} }class Trie {Node root;public Trie() {root = new Node();}public void insert(String word) {char[] chars = word.toCharArray();Node cur = root;for (int i = 0; i < chars.length; i++) {if (cur.get(chars[i]) != null) {cur = cur.get(chars[i]);} else {cur = cur.put(chars[i]);}if (i == chars.length - 1) {cur.isEnd = true;}}}/*** Returns if the word is in the trie.*/public boolean search(String word) {Node node = searchPrefix(root, word, 0, true);return node != null && node.isEnd;}// 從node開始,在是否剩余tolerance的情況下,是否能匹配從i開始的后續(xù)字符串public Node searchPrefix(Node node, String str, int i, boolean tolerance) {if (node == null) return null;if (i == str.length()) return tolerance ? null : node;Node cur = node;if (!tolerance) { // 已無tolerance,直接匹配for (int j = i; j < str.length(); j++) {char c = str.charAt(j);if (cur.get(c) == null) return null;else cur = cur.get(c);}return cur;} else { // 有tolerance,先DFS消耗tolerance, 再遞歸匹配for (int j = 0; j < cur.map.length; j++) {// 當 j==str.charAt(i)-'a' 時,此次不消耗tolerance// 當 j!=str.charAt(i)-'a' 時,此次消耗toleranceNode failover = searchPrefix(cur.map[j], str, i + 1, j == str.charAt(i) - 'a');if (failover != null && failover.isEnd) return failover;}}return null;} }class MagicDictionary {Trie trie;public MagicDictionary() {trie = new Trie();}public void buildDict(String[] dictionary) {for (String s : dictionary) {trie.insert(s);}}public boolean search(String searchWord) {return trie.search(searchWord);} }/*** Your MagicDictionary object will be instantiated and called as such:* MagicDictionary obj = new MagicDictionary();* obj.buildDict(dictionary);* boolean param_2 = obj.search(searchWord);*/總結(jié)
以上是生活随笔為你收集整理的leetcode 676. Implement Magic Dictionary | 676. 实现一个魔法字典(DFS+Trie 前缀树)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Why is it recommende
- 下一篇: 糟糕程序员的20个坏习惯