面试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;
    }
}
相关推荐
零雲5 小时前
java面试:有了解过RocketMq架构么?详细讲解一下
java·面试·java-rocketmq
卡卡酷卡BUG6 小时前
Java 后端面试干货:四大核心模块高频考点深度解析
java·开发语言·面试
我命由我123459 小时前
Photoshop - Photoshop 工具栏(22)单行选框工具
学习·ui·职场和发展·求职招聘·职场发展·学习方法·photoshop
沐怡旸9 小时前
【底层机制】LeakCanary深度解析:从对象监控到内存泄漏分析的完整技术体系
android·面试
Moonbit9 小时前
招募进行时 | MoonBit AI : 程序语言 & 大模型
前端·后端·面试
uhakadotcom10 小时前
基于 TOON + Next.js 来大幅节省 token 并运行大模型
前端·面试·github
野生技术架构师11 小时前
牛客网Java 高频面试题总结(2025最新版)
java·开发语言·面试
王中阳Go11 小时前
又整理了一场真实Golang面试复盘!全是高频坑+加分话术,面试遇到直接抄
后端·面试·go