leetcode 地址:
https://leetcode.com/problems/implement-trie-prefix-tree/description/
难度:中等
描述:略
解题思路:
Trie树 也就是字典查找树,是一种能够实现在一个字符串集中实现快速查找和匹配的多叉树结构,关于Trie树的深入分析我就不展开了,因为我自己也理解的不深刻^_^,这里只给出Trie树的定义,以及常用的应用场景,然后给出一个简单的java实现,当然代码简洁性和性能上有很大的优化空间。
首先,Trie树的定义(或者说是性质):
1. 根节点是一个空节点,不包含字符
2. 每个节点含有一个字符,以及若干个子节点
3. 每个节点的所有子节点所包含的字符都不相同
3. 树的每个节点到根节点的路径上的所有字符组成一个字符串,表示这个字符串在树中可能存在,或者至少Trie树中存在以此字符串为前缀的字符串
4. 每个非根节点还应该包含一个整型数值,表示根节点到这个节点组成的字符串在Trie树中出现的次数
Trie数的常见应用场景:
1. 字符串检索
2. 词频统计
3. 前缀检索
4.前缀词频统计
5. 对所有的字符串按照字典序排序
java实现:
public class Trie { public static void main(String[] args) { Trie trie = new Trie(); trie.insert("apple"); System.out.println(trie.search("apple")); System.out.println(trie.search("app")); // returns false System.out.println(trie.startsWith("app")); // returns true trie.insert("app"); System.out.println(trie.search("app")); // returns true } TrieNode root; /** * Initialize your data structure here. */ public Trie() { root = new TrieNode(); } /** * Inserts a word into the trie. */ public void insert(String word) { insert(word, root, 0); } /** * 将从index处开始的字串插入到root的子节点中,即将index对应的字符插入到root的子节点中 * @param word * @param root * @param index */ private void insert(String word, TrieNode root, int index) { assert index < word.length() && index > -1; char cur = word.charAt(index); TreeMap<Character, TrieNode> children = root.children; if (null == children) { children = new TreeMap<>(); root.children = children; } if (!children.containsKey(cur)) { children.put(cur, new TrieNode(cur)); } if (index == word.length() - 1) { children.get(cur).occurency++; return; } insert(word, children.get(cur), index + 1); } /** * Returns if the word is in the trie. */ public boolean search(String word) { return search(word, root, 0); } /** * 在root的子节点中搜索从index开始的字串 * @param word * @param root * @param index * @return */ private boolean search(String word, TrieNode root, int index) { assert index > -1 && index < word.length(); char cur = word.charAt(index); if (root.children == null || !root.children.containsKey(cur)) { return false; } if (index == word.length() - 1) { return root.children.get(cur).occurency > 0; } return search(word, root.children.get(cur), index + 1); } /** * Returns if there is any word in the trie that starts with the given prefix. */ public boolean startsWith(String prefix) { return startsWith(prefix, root, 0); } /** * 在root的子节点中搜索从index开始字串对应的前缀 * @param prefix * @param root * @param index * @return */ private boolean startsWith(String prefix, TrieNode root, int index) { assert index > -1 && index < prefix.length(); char cur = prefix.charAt(index); if (root.children == null || !root.children.containsKey(cur)) { return false; } if (index == prefix.length() - 1) { return true; } return startsWith(prefix, root.children.get(cur), index + 1); } static class TrieNode { char c; int occurency = 0; TreeMap<Character, TrieNode> children; public TrieNode() { } public TrieNode(char c) { this.c = c; } } }