208:前缀树

题意

Trie(发音类似 "try")或者说 前缀树 是一种树形数据结构,用于高效地存储和检索字符串数据集中的键。这一数据结构有相当多的应用情景,例如自动补完和拼写检查。

请你实现 Trie 类:

Trie() 初始化前缀树对象。
void insert(String word) 向前缀树中插入字符串 word。
boolean search(String word) 如果字符串 word 在前缀树中,返回 true(即,在检索之前已经插入);否则,返回 false。
boolean startsWith(String prefix) 如果之前已经插入的字符串 word 的前缀之一为 prefix,返回 true;否则,返回 false。

分析

前缀树是一种树形结构,其将一个字符串表示在一棵树中,例如:


绘图1.png

其中保存了数据【APP、APPLE、TIRE】其中,黄色节点表示含有这个对象,蓝色表示只是路径节点。
注意:前缀树是有一个总的虚拟头节点。

题解

// 定义节点结构
class TireNode {
    char value;// 当前节点的值
    boolean isExists = false;// 当前节点是都被包含【上述黄色节点】
    HashMap children = new HashMap();//【具体的分支】

    public TireNode(char value) {
        this.value = value;
    }
}
// 实现前缀树
class Trie {
    // 虚拟头节点
    TireNode dummyHead = new TireNode('-');

    public void insert(String word) {
        // 处理特殊情况
        if (word == null || word.length() == 0) return;
        // 是否需要创建根节点
        insertSub(word, 0, dummyHead.children);
    }

    // 将指定元素插入前缀树的指定位置
    public void insertSub(String word, int start, HashMap children) {
        // 插入到元素末尾,直接返回
        if (start == word.length()) return;

        if (children.containsKey(word.charAt(start))) {
            TireNode tireNodeTemp = children.get(word.charAt(start));
            // 判断是否存在当前元素
            if (start == word.length() - 1) tireNodeTemp.isExists = true;
            insertSub(word, start + 1, tireNodeTemp.children);
            // 不包含当前节点
        } else {
            TireNode node = new TireNode(word.charAt(start));
            // 判断是否存在当前元素
            if (start == word.length() - 1) node.isExists = true;
            children.put(word.charAt(start), node);
            // 插入元素
            insertSub(word, start + 1, node.children);
        }
    }

     // 查找特定字符串
    public boolean search(String word) {
        TireNode tireNodeResult = searchSub(word, 0, dummyHead.children.get(word.charAt(0)));
        if (tireNodeResult == null) return false;
        return tireNodeResult.isExists;
    }


    public TireNode searchSub(String word, int start, TireNode tireNode) {
        if (tireNode == null) return null;
        if (tireNode.value == word.charAt(start)) {
            if (start == word.length() - 1) return tireNode;
            // 寻找下一个字符
            if (start + 1 < word.length())
                return searchSub(word, start + 1, tireNode.children.get(word.charAt(start + 1)));
        }
        return null;
    }

    // 是否有前缀
    public boolean startsWith(String prefix) {
        TireNode tireNodeResult = searchSub(prefix, 0, dummyHead.children.get(prefix.charAt(0)));
        if (tireNodeResult == null) return false;
        return true;
    }

}

你可能感兴趣的:(208:前缀树)