面试150——字典树

208. 实现 Trie (前缀树)


思路

字典树的每条边代表一个字符,从根节点到某一节点的路径表示一个字符串。如果某节点被标记为结束节点,则表示该路径对应的字符串存在于集合中。

代码

java 复制代码
class Trie {
    Trie[] children;
    boolean isEnd;
    public Trie() {
        children = new Trie[26];
        isEnd = false;
    }
    
    public void insert(String word) {
        Trie node = this; // 获取当前节点
        for (char c : word.toCharArray()) {
            int index = c - 'a';
            if (node.children[index] == null) node.children[index] = new Trie();
            node = node.children[index];
        }
        node.isEnd = true;
    }
    
    public boolean search(String word) {
        Trie node = this;
        for (char c : word.toCharArray()) {
            int index = c - 'a';
            if (node.children[index] == null) return false;
            node = node.children[index];
        }
        return node.isEnd;
    }
    
    public boolean startsWith(String prefix) {
        Trie node = this;
        for (char c : prefix.toCharArray()) {
            int index = c - 'a';
            if (node.children[index] == null) return false;
            node = node.children[index];
        }
        return true;
    }
}

211. 添加与搜索单词 - 数据结构设计


思路

addWord就是正常的insert方法,search由于存在'.'代表任何一个数字,因此需要特判,分多种情况往下搜索dfs。
代码

java 复制代码
class WordDictionary {
    WordDictionary[] children;
    boolean isEnd;
    public WordDictionary() {
        children = new WordDictionary[26];
        isEnd = false;
    }
    
    public void addWord(String word) {
        WordDictionary node = this;
        for (char c : word.toCharArray()) {
            int index = c - 'a';
            if (node.children[index] == null) node.children[index] = new WordDictionary();
            node = node.children[index];
        }
        node.isEnd = true;
    }
    
    public boolean search(String word) {
        return dfs(this, word, 0);
    }

    public boolean dfs(WordDictionary root, String word, int index) {
        if (index == word.length()) {
            return root.isEnd;
        }
        char c = word.charAt(index);
        boolean flag = false;
        if (c != '.') {
            int i = c - 'a';
            if (root.children[i] == null) flag |= false;
            else flag |= dfs(root.children[i], word, index + 1);
        } else {
            for (int i = 0; i < 26; i ++) {
                if (root.children[i] == null) flag |= false;
                else flag |= dfs(root.children[i], word, index + 1);
            }
        }
        return flag;
    }
}

212. 单词搜索 II


思路

创建字典树,将单词列表的单词都添加到字典树中。之后在网格中全局搜索,以某个位置为起点搜索全网格,之后判断当前字符串是否在字典树中。
代码

java 复制代码
class Solution {
    Set<String> res;
    StringBuilder path;
    Trie trie; 
    int[][] directions = new int[][] {{-1, 0}, {1, 0}, {0, 1}, {0, -1}};
    boolean[][] used;
    public List<String> findWords(char[][] board, String[] words) {
        int n = board.length, m = board[0].length;
        path = new StringBuilder();
        trie = new Trie();
        res = new HashSet<>();
        used = new boolean[n][m];
        for (String word : words) trie.insert(word);
        for (int i = 0; i < n; i ++) {
            for (int j = 0; j < m; j ++) {
                char c = board[i][j];
                int index = c - 'a';
                if (trie.children[index] != null) {
                    used[i][j] = true;
                    path.append(c);
                    backtrace(board, i, j, trie.children[index]);
                    path.deleteCharAt(path.length() - 1);
                    used[i][j] = false;
                }
            }
        }
        return new ArrayList<>(res);
    }

    void backtrace(char[][] board, int x, int y, Trie cur) {
        int n = board.length, m = board[0].length;
        if (cur.isEnd) {
            res.add(path.toString());
        }

        for (int[] direction : directions) {
            int i = x + direction[0], j = y + direction[1];
            if (i >= 0 && i < n && j >= 0 && j < m && ! used[i][j]) {
                char c = board[i][j];
                int index = c - 'a';
                if (cur.children[index] == null) continue;
                else {
                    used[i][j] = true;
                    path.append(c);
                    backtrace(board, i, j, cur.children[index]);
                    path.deleteCharAt(path.length() - 1);
                    used[i][j] = false;
                }
            }
        }
    }

}

class Trie {
    Trie[] children;
    boolean isEnd;
    Trie() {
        this.children = new Trie[26];
        this.isEnd = false;
    }
    void insert(String word) {
        Trie node = this;
        for (char c : word.toCharArray()) {
            int index = c - 'a';
            if (node.children[index] == null) node.children[index] = new Trie();
            node = node.children[index];
        }
        node.isEnd = true;
    }
}
相关推荐
测试涛叔7 小时前
金三银四软件测试面试题(800道)
软件测试·面试·职场和发展
Angelina_Jolie8 小时前
一文搞懂 SCI、SSCI、CSSCI、C 刊、核心期刊:定义、作用、层级对比及投稿选择
考研·职场和发展·创业创新
C雨后彩虹9 小时前
计算疫情扩散时间
java·数据结构·算法·华为·面试
蒹葭玉树10 小时前
【C++上岸】C++常见面试题目--操作系统篇(第二十八期)
linux·c++·面试
User_芊芊君子10 小时前
【LeetCode经典题解】搞定二叉树最近公共祖先:递归法+栈存路径法,附代码实现
算法·leetcode·职场和发展
熬夜造bug10 小时前
LeetCode Hot100 刷题路线(Python版)
算法·leetcode·职场和发展
多米Domi01112 小时前
0x3f 第48天 面向实习的八股背诵第五天 + 堆一题 背了JUC的题,java.util.Concurrency
开发语言·数据结构·python·算法·leetcode·面试
测试者家园15 小时前
测试用例智能生成:是效率革命,还是“垃圾进,垃圾出”的新挑战?
人工智能·职场和发展·测试用例·测试策略·质量效能·智能化测试·用例设计
win x17 小时前
JavaSE(基础)高频面试点及 知识点
java·面试·职场和发展
编程彩机17 小时前
互联网大厂Java面试:从分布式缓存到消息队列的技术场景解析
java·redis·面试·kafka·消息队列·微服务架构·分布式缓存