[LeetCode] 208. Implement Trie (Prefix Tree) 實現字典樹(前綴樹)
阿新 • • 發佈:2018-03-07
分享 [] child height 查找樹 new t 實施 dex data
Implement a trie with insert
, search
, and startsWith
methods.
Note:
You may assume that all inputs are consist of lowercase letters a-z
.
實現一個數據結構:字典樹(前綴樹或單詞查找樹),具備insert, search, startsWith的功能。參考董的博客:數據結構之Trie樹
Trie樹,又稱字典樹,單詞查找樹或者前綴樹,是一種用於快速檢索的多叉樹結構,如英文字母的字典樹是一個26叉樹,數字的字典樹是一個10叉樹。Trie樹可以利用字符串的公共前綴來節約存儲空間。
Trie樹的基本性質可以歸納為:
(1)根節點不包含字符,除根節點以外每個節點只包含一個字符。
(2)從根節點到某一個節點,路徑上經過的字符連接起來,為該節點對應的字符串。
(3)每個節點的所有子節點包含的字符串不相同。
下圖是一個保存了8個鍵的trie結構,"A", "to", "tea", "ted", "ten", "i", "in", and "inn"
Trie樹復雜度:
(1)插入、查找的時間復雜度均為O(N),其中N為字符串長度。
(2) 空間復雜度是26^n級別的,非常龐大(可采用雙數組實現改善)。
實施方法:因為只用26個字母,所以可以用數組記錄,數組元素為TrieNode。
Java:
class TrieNode { private TrieNode[] children; public boolean hasWord; // Initialize your data structure here. public TrieNode() { children = new TrieNode[26]; hasWord = false; } public void insert(String word, int index) { if (index == word.length()) { this.hasWord = true; return; } int pos = word.charAt(index) - ‘a‘; if (children[pos] == null) { children[pos] = new TrieNode(); } children[pos].insert(word, index + 1); } public TrieNode find(String word, int index) { if (index == word.length()) { return this; } int pos = word.charAt(index) - ‘a‘; if (children[pos] == null) { return null; } return children[pos].find(word, index + 1); } } public class Trie { private TrieNode root; public Trie() { root = new TrieNode(); } // Inserts a word into the trie. public void insert(String word) { root.insert(word, 0); } // Returns if the word is in the trie. public boolean search(String word) { TrieNode node = root.find(word, 0); return (node != null && node.hasWord); } // Returns if there is any word in the trie // that starts with the given prefix. public boolean startsWith(String prefix) { TrieNode node = root.find(prefix, 0); return node != null; } }
Python: Time: O(n), per operation, Space: O(1)
class TrieNode: def __init__(self): # Initialize your data structure here. self.childs = dict() self.isWord = False class Trie: def __init__(self): self.root = TrieNode() # @param {string} word # @return {void} # Inserts a word into the trie. def insert(self, word): node = self.root for letter in word: child = node.childs.get(letter) if child is None: child = TrieNode() node.childs[letter] = child node = child node.isWord = True # @param {string} word # @return {boolean} # Returns if the word is in the trie. def search(self, word): node = self.root for letter in word: node = node.childs.get(letter) if node is None: return False return node.isWord # @param {string} prefix # @return {boolean} # Returns if there is any word in the trie # that starts with the given prefix. def startsWith(self, prefix): node = self.root for letter in prefix: node = node.childs.get(letter) if node is None: return False return True
Python:
class TrieNode: def __init__(self): self.is_string = False self.leaves = {} class Trie: def __init__(self): self.root = TrieNode() def insert(self, word): cur = self.root for c in word: if not c in cur.leaves: cur.leaves[c] = TrieNode() cur = cur.leaves[c] cur.is_string = True def search(self, word): node = self.childSearch(word) if node: return node.is_string return False def startsWith(self, prefix): return self.childSearch(prefix) is not None def childSearch(self, word): cur = self.root for c in word: if c in cur.leaves: cur = cur.leaves[c] else: return None return cur
C++:
class TrieNode { public: // Initialize your data structure here. TrieNode() : is_string(false) { } bool is_string; unordered_map<char, TrieNode *> leaves; }; class Trie { public: Trie() { root_ = new TrieNode(); } void insert(string word) { auto *cur = root_; for (const auto& c : word) { if (!cur->leaves.count(c)) { cur->leaves[c] = new TrieNode(); } cur = cur->leaves[c]; } cur->is_string = true; } bool search(string word) { auto *node = childSearch(word); if (node) { return node->is_string; } return false; } bool startsWith(string prefix) { return childSearch(prefix); } TrieNode *childSearch(const string& word) { auto *cur = root_; for (const auto& c : word) { if (cur->leaves.count(c)) { cur = cur->leaves[c]; } else { return nullptr; } } return cur; } private: TrieNode *root_; };
[LeetCode] 208. Implement Trie (Prefix Tree) 實現字典樹(前綴樹)