A trie (pronounced as "try") or prefix tree is a tree data structure used to efficiently store and retrieve keys in a dataset of strings. There are various applications of this data structure, such as autocomplete and spellchecker.
Implement the Trie class:
Trie()
Initializes the trie object.void insert(String word)
Inserts the string word
into the trie.boolean search(String word)
Returns true
if the string word
is in the trie (i.e., was inserted before), and false
otherwise.boolean startsWith(String prefix)
Returns true
if there is a previously inserted string word
that has the prefix prefix
, and false
otherwise.Example 1:
Input ["Trie", "insert", "search", "search", "startsWith", "insert", "search"] [[], ["apple"], ["apple"], ["app"], ["app"], ["app"], ["app"]] Output [null, null, true, false, true, null, true] Explanation Trie trie = new Trie(); trie.insert("apple"); trie.search("apple"); // return True trie.search("app"); // return False trie.startsWith("app"); // return True trie.insert("app"); trie.search("app"); // return True
The task is to implement a Trie (pronounced "try") data structure, which is used to efficiently store and retrieve keys (words) in a dataset of strings. The Trie allows for quick searches and prefix matching. The Trie consists of nodes, where each node represents a character in a word. The edges between nodes represent characters, and each path from the root to a node forms a word.
Trie Node:
Implement a trienode class with attributes:
children: A dictionary mapping characters to child nodes.
endofword: A boolean indicating whether the current node marks the end of a word.
Trie Class:
Implement a Trie class with methods:
init: Initializes an empty Trie with a root node.
insert: Inserts a word into the Trie by iterating over its characters and creating nodes as needed.
search: Searches for a complete word in the Trie by traversing the Trie and checking if the endofword attribute is True.
startsWith: Checks if there is a path in the Trie that matches the given prefix.
Insertion:
During insertion, iterate over each character of the word.
If the character is not already a child of the current node, create a new child node.
Move to the next node and repeat the process until all characters are inserted.
Search:
During search, iterate over each character of the word.
If a character is not found as a child of the current node, return False.
If all characters are found, check if the endofword attribute is True to ensure the word is complete.
Prefix Matching:
During prefix matching, iterate over each character of the prefix.
If a character is not found as a child of the current node, return False.
If all characters are found, return True to indicate the existence of a path with the given prefix.
Insertion: The time complexity of insertion is O(m), where m is the length of the word being inserted.
Search: The time complexity of search is O(m), where m is the length of the word being searched.
StartsWith: The time complexity of prefix matching is O(m), where m is the length of the prefix.
The space complexity of the Trie depends on the number of unique words and the length of the words. In the worst case, where there are no common prefixes among the words, the space complexity is O(n * m), where n is the number of words and m is the average length of the words.
class trienode:
def __init__(self):
self.children = {}
self.endofword = False
class Trie:
def __init__(self):
self.root = trienode()
def insert(self, word: str) -> None:
cur = self.root
for c in word:
if c not in cur.children:
cur.children[c] = trienode()
cur = cur.children[c]
cur.endofword = True
def search(self, word: str) -> bool:
cur = self.root
for c in word:
if c not in cur.children:
return False
cur = cur.children[c]
return cur.endofword
def startsWith(self, prefix: str) -> bool:
cur = self.root
for c in prefix:
if c not in cur.children:
return False
cur = cur.children[c]
return True
# Your Trie object will be instantiated and called as such:
# obj = Trie()
# obj.insert(word)
# param_2 = obj.search(word)
# param_3 = obj.startsWith(prefix)