1. 用什么数据结构?

      • 在 TrieNode 对象 设置一个长度为26的 TrieNode 数组
      • 或者预估问题规模,利用预先定义二维数组
    2. 需要判断当前前缀是否构成单词!

      • 需要加上 isEnd 变量记录
    1. 模板如下
    • leetcode 208

      1. class Trie {
      2. private Trie[] children; // 对应 26个字母
      3. private boolean isEnd; // 判断当前前缀是否是一个单词
      4. public Trie() {
      5. children = new Trie[26];
      6. isEnd = false;
      7. }
      8. public void insert(String word) {
      9. Trie node = this;
      10. for (int i = 0; i < word.length(); i++) {
      11. char ch = word.charAt(i);
      12. int index = ch - 'a';
      13. if (node.children[index] == null) { // 建立下一层前缀树结点
      14. node.children[index] = new Trie();
      15. }
      16. node = node.children[index];
      17. }
      18. node.isEnd = true;
      19. }
      20. public boolean search(String word) {
      21. Trie node = searchPrefix(word);
      22. return node != null && node.isEnd;
      23. }
      24. public boolean startsWith(String prefix) {
      25. return searchPrefix(prefix) != null;
      26. }
      27. private Trie searchPrefix(String prefix) {
      28. Trie node = this;
      29. for (int i = 0; i < prefix.length(); i++) {
      30. char ch = prefix.charAt(i);
      31. int index = ch - 'a';
      32. if (node.children[index] == null) {
      33. return null;
      34. }
      35. node = node.children[index];
      36. }
      37. return node;
      38. }
      39. }
    • leetcode 211 (利用 dfs 实现字典树的插入和查找,且适配通配符 ‘.’)

      class Trie {
        Trie[] children;
        boolean isEnd; // 判断当前前缀是否是完整的单词
        Trie() {
            children = new Trie[26];
            isEnd = false;
        }
        private void helpBuild(String word, Trie node, int i, int n) {
            if(i == n) {  // 遍历字符串完成,插入成功
                node.isEnd = true;
                return;
            }
            if(word.charAt(i) == '.') {   // . 为通配符,可适配任何小写字母
                for(int k = 0; k < 26; k++) {
                    if(node.children[k] == null) {
                        node.children[k] = new Trie();
                    }
                    helpBuild(word, node.children[k], i+1, n);
                }
            }else {
                int index = word.charAt(i) - 'a';
                if(node.children[index] == null) {
                    node.children[index] = new Trie();
                }
                helpBuild(word, node.children[index], i+1, n);
            }
        }
        public void insert(String word) {
            if(word == null || word.length() == 0) {
                return;
            }
            Trie node = this;
      
            // 递归建立字典树
            helpBuild(word, node, 0, word.length());
        }
        private boolean helpSearch(String word, Trie node, int i, int n) {
            if(i == n) {
                return node.isEnd;
            }
            if(word.charAt(i) == '.') {  // 通配符
                boolean ans = false;
                for(int k = 0; k < 26; k++) {    // 在26个分支中,只要有1个匹配成功即可,不需要搜索所有情况
                    if(node.children[k] != null) {
                        ans = ans || helpSearch(word, node.children[k], i+1, n);
                        if(ans == true) {
                            return true;
                        }
                    }
                }
                return ans;
            }else {
                int index = word.charAt(i) - 'a';
                if(node.children[index] == null) {
                    return false;
                }
                else {
                    return helpSearch(word, node.children[index], i+1, n);
                }
            }
            //return false;
        }
        public boolean search(String word) {
            Trie node = this;
            return helpSearch(word, node, 0, word.length());
        }
      }
      class WordDictionary {
        Trie trie;
      
        public WordDictionary() {
            trie = new Trie();
        }
      
        public void addWord(String word) {
            trie.insert(word);
        }
      
        public boolean search(String word) {
            return trie.search(word);
        }
      }
      
    1. 算法分析

      针对 leetcode 211 时间复杂度 :初始化为 O(1),插入为 O(|S|),查找为 O( 26^{|S|}) ,|S| 为字符串长 空间复杂度:O( L^{26}),L 为所有字符串的长度总和