trie树(前缀树)

208. 实现 Trie (前缀树)    中等

实现一个 Trie (前缀树),包含 insertsearch, 和 startsWith 这三个操作。

示例:

Trie trie = new Trie();

trie.insert("apple");
trie.search("apple");   // 返回 true
trie.search("app");     // 返回 false
trie.startsWith("app"); // 返回 true
trie.insert("app");   
trie.search("app");     // 返回 true

说明:

  • 你可以假设所有的输入都是由小写字母 a-z 构成的。
  • 保证所有输入均为非空字符串。
class Trie {

    private TrieNode root;

    public Trie() {
        root = new TrieNode();
    }

    /**
     * 向 Trie 树中插入键
     * 我们通过搜索 Trie 树来插入一个键。我们从根开始搜索它对应于第一个键字符的链接。有两种情况:
     *     链接存在。沿着链接移动到树的下一个子层。算法继续搜索下一个键字符。
     *     链接不存在。创建一个新的节点,并将它与父节点的链接相连,该链接与当前的键字符相匹配。
     * 重复以上步骤,直到到达键的最后一个字符,然后将当前节点标记为结束节点,算法完成。
     */
    public void insert(String word) {
        TrieNode node = root;
        for (int i = 0; i < word.length(); i++) {
            char currentChar = word.charAt(i);
            if (!node.containsKey(currentChar)) {
                node.put(currentChar, new TrieNode());
            }
            node = node.get(currentChar);
        }
        node.setEnd();
    }

    /**
     * 在 Trie 树中查找键
     * 每个键在 trie 中表示为从根到内部节点或叶的路径。我们用第一个键字符从根开始。检查当前节点中与键字符对应的链接。有两种情况:
     * 存在链接。我们移动到该链接后面路径中的下一个节点,并继续搜索下一个键字符。
     *      不存在链接。若已无键字符,且当前结点标记为 isEnd,则返回 true。否则有两种可能,均返回 false :
     *      还有键字符剩余,但无法跟随 Trie 树的键路径,找不到键。
     *      没有键字符剩余,但当前结点没有标记为 isEnd。也就是说,待查找键只是Trie树中另一个键的前缀。
     */
    private TrieNode searchPrefix(String word) {
        TrieNode node = root;
        for (int i = 0; i < word.length(); i++) {
            char currentChar = word.charAt(i);
            if (node.containsKey(currentChar)) {
                node = node.get(currentChar);
            } else {
                return null;
            }
        }
        return node;
    }
    public boolean search(String word) {
        TrieNode node = searchPrefix(word);
        return node != null && node.isEnd();
    }
    
    public boolean startsWith(String prefix) {
        TrieNode node = searchPrefix(prefix);
        return node != null;
    }

    /**
     *     Trie 树的结点结构
     *     最多 R 个指向子结点的链接,其中每个链接对应字母表数据集中的一个字母。
     *     假定 R 为 26,小写拉丁字母的数量。
     *     布尔字段,以指定节点是对应键的结尾还是只是键前缀。
     */
    class TrieNode {
        private TrieNode[] nodes;
        private boolean isEnd;
        private final int R = 26;

        public TrieNode() {
            nodes = new TrieNode[R];
        }

        public boolean containsKey(char ch) {
            return nodes[ch - 'a'] != null;
        }

        public TrieNode get(char ch) {
            return nodes[ch - 'a'];
        }

        public void put(char ch, TrieNode node) {
            nodes[ch - 'a'] = node;
        }

        public void setEnd() {
            isEnd = true;
        }

        public boolean isEnd() {
            return isEnd;
        }
    }
}

应用:自动补全 拼音检查 IP路由(最长前缀匹配)  T9 (九宫格)打字预测 单词游戏

猜你喜欢

转载自blog.csdn.net/qq_43204550/article/details/108604462