208.实现前缀树

题目描述

实现一个 Trie (前缀树),包含 insert, search, 和 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 构成的。
保证所有输入均为非空字符串。


题解过程

思路
  • 先定义Trienode数据结构
    • 三个private初始定义
      • Trienode[] links
      • R=26
      • isEnd
    • 一个构造函数
      • 创建前缀树
    • 五大方法
      • 节点是否存在 containsKey()
      • 获取节点 get()
      • 放置节点 put()
      • 设置终点 setEnd()
      • 查看是否为终点 isEnd()
  • 写Trie类
    • 初始化root
    • 构造 Trie()
    • insert()
      • 新建node->获取字符->判断是否存在该字符
        • 不存在->放置字符,再获取字符所在节点
        • (存在)获取字符所在节点
      • 循环结束,设置终点
    • search()
      • 调用searchPrefix()
        • 新建node->获取字符->判断是否存在该字符
          • 存在,获取字符
          • 否则(不存在),置null,
          • 返回node
        • 循环结束,返回node
      • 判断不为空且在终点
    • startsWith()
      • 调用searchPrefix()
      • 判断不为空
完整代码
//数据结构
class TrieNode {
    // R links to node children
    //前缀树节点数组
    private TrieNode[] links; 
    //每个节点由26个字符
    private final int R = 26;
    //判断是否到达结尾
    private boolean isEnd;
    //新建前缀树节点
    public TrieNode() {
        //别忘了节点数R
        links = new TrieNode[R];
    }
    //是否包含该字符
    public boolean containsKey(char ch) {
        return links[ch -'a'] != null;
    }
    //获取该字符
    public TrieNode get(char ch) {
        return links[ch -'a'];
    }
    //放置该节点进入links中
    public void put(char ch, TrieNode node) {
        links[ch -'a'] = node;
    }
    //若到达终点,将isEnd置true
    public void setEnd() {
        isEnd = true;
    }
    //判断是否已经到终点
    public boolean isEnd() {
        return isEnd;
    }
}
//前缀树,又称字典树,单词查找树
class Trie {
    //获取根节点。
    private TrieNode root;
    //初始化根节点
    public Trie() {
        root = new TrieNode();
    }
    // Inserts a word into the trie.
    public void insert(String word) {
        //新建node为root
        TrieNode node = root;
        for (int i = 0; i < word.length(); i++) {
            //当前字符
            char currentChar = word.charAt(i);
            //若不存在,则放置
            if (!node.containsKey(currentChar)) {
            //要新建一个节点放进去 ,new TrieNode() 不然会出现引用
                node.put(currentChar, new TrieNode());
            }
            //沿着链接移动到下一个子层,搜索下个字符
            node = node.get(currentChar);
        }
        //到达最后一个,设置为终点
        node.setEnd();
    }
     public boolean search(String word) {
         //获取该前缀树
       TrieNode node = searchPrefix(word);
       //不为空且为终点,则返回true
       return node != null && node.isEnd();
    }
    //TrieNode是私人的private
    private TrieNode searchPrefix(String word) {
        //获取根节点
        TrieNode node = root;
        //下面两行可以改成for(char temp:word.toCharArray()){
        for (int i = 0; i < word.length(); i++) {
            //获取字符
           char curLetter = word.charAt(i);
           //存在,取该字符,否则,返回null
           if (node.containsKey(curLetter)) {
               node = node.get(curLetter);
           } else {
               //这里是return null  而不是 node=null   
               return null;
           }
        }
        //返回该前缀数
        return node;
    }
    //查找键前缀,而不是整棵树
    public boolean startsWith(String prefix) {
        //同查找键,区别在于不判断是否在尾巴
        TrieNode node = searchPrefix(prefix);
        return node != null;
    }
}

插入: 时间O(m) 空间(m)
查找键/键前缀: 时间O(m) 空间O(1)

发布了13 篇原创文章 · 获赞 0 · 访问量 303

猜你喜欢

转载自blog.csdn.net/m0_37605197/article/details/105021034
今日推荐