Leetcode208. 实现Trie(前缀树)[Med] -JAVA

@[TOC](Leetcode208. 实现Trie(前缀树)[Med] -JAVA)

题目

实现一个 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 构成的。 保证所有输入均为非空字符串。

Related Topics 设计 字典树

思路

什么是Trie(前缀树)? 有一批单词,a、an、apple、apply、cat 、can、dog 我们肉眼可以直接看出a前缀的有a,an,apple,apply 这几个单词,以app 为前缀有的apple,apply,以c为前缀的有cat,can 如果让你判断某个单位是否存在列表中,一个个字词再到一个个字符比对显然很没有效率,所以我们建立一个前缀树,如下

  root(只是一个入口)
   /    
  a    c   d
 /    /   /
n  p   a   o
   /   /  /
  p   t   g
  /
  l
 / 
 e y

当要进行查询时,根据前缀树可以快速的找到对应的单词。 就如同在搜索引擎上,当你打上java,搜索下拉框就会出现以java为前缀的句子,讲到这应该大致明白了。 如何实现? 其实有点像链表。 我们定义一个类,来表示每个节点,而每个节点的子节点用Map装起来,而 map 的value也是这样的节点类,是不是很像链表。 insert时通过遍历单词的字符,如果存在当前字符就继续向下走,如果不存在就新建节点,将当前字符做为key. 这里注意下要在在node 中使用isEnd来做标记,是否当前节点是一个单词的结束节点。这样就可以找一个完整的单词了。 search时通过遍历单词的字符,每个字符都在当前节点的map里找有没有相关的字符,一旦没有就可以终止了。使用isEnd来判断是否为单词的结束 startWith时,找前缀同search一样,但是不用判断isEnd,找完就结束。 结合代码注释看下吧!

解法

class Trie {

    class Node {
        char c;//前缀字符
        HashMap<Character, Node> subNode = new HashMap<>();//用于装子节点
        boolean isEnd;//一个完整单词的终点
        public Node(char c) {
            this.c = c;
        }
    }

    Node root;

    public Trie() {
        root = new Node( );
    }
    
    public void insert(String word) {
        Node current = root;
        for (int i = 0; i < word.length(); i++) {
            char c = word.charAt(i);
            current.subNode.putIfAbsent(c,new Node(c));//为节点赋值
            current = current.subNode.get(c);//为下个节点连接做准备,选好父节点
        }
        current.isEnd=true;//一个完整的单词结束
    }
    
    public boolean search(String word) {
        Node current = root;
        for (int i = 0; i < word.length(); i++) {
            char c = word.charAt(i);
            Node node = current.subNode.get(c);
            if (node==null) return false;
            current = node;
        }
        return current.isEnd;//需要判断是否是一个单词的终点
    }
    
    public boolean startsWith(String prefix) {
        Node current = root;
        for (int i = 0; i < prefix.length(); i++) {
            char c = prefix.charAt(i);
            Node node = current.subNode.get(c);
            if (node==null) return false;
            current = node;
        }
        return true;//同search一样,只是不用判断是否为一个完整的单词,有前缀即可
    }
}
经验分享 程序员 微信小程序 职场和发展