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; } } }