Problem
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 stringword
into the trie.int countWordsEqualTo(String word)
Returns the number of instances of the stringword
in the trie.int countWordsStartingWith(String prefix)
Returns the number of strings in the trie that have the stringprefix
as a prefix.void erase(String word)
Erases the stringword
from the trie.
Examples
Example 1:
|
|
Constraints:
1 <= word.length, prefix.length <= 2000
word
andprefix
consist only of lowercase English letters.- At most
3 * 10^4
calls in total will be made toinsert
,countWordsEqualTo
,countWordsStartingWith
, anderase
. - It is guaranteed that for any function call to
erase
, the stringword
will exist in the trie.
Solution
Method 1 – Trie with Count Tracking
Intuition
We need to support insert, erase, and two types of count queries efficiently. A Trie (prefix tree) is ideal for prefix-based operations, and we can augment each node to track the number of words passing through and ending at that node.
Approach
- Each Trie node stores:
children
: mapping for next characters.cnt
: number of words passing through this node (for prefix count).end
: number of words ending at this node (for exact word count).
- For
insert
, traverse the Trie, incrementingcnt
at each node andend
at the last node. - For
countWordsEqualTo
, traverse to the end node and returnend
. - For
countWordsStartingWith
, traverse to the prefix node and returncnt
. - For
erase
, traverse the Trie, decrementingcnt
at each node andend
at the last node.
Code
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Complexity
- ⏰ Time complexity:
O(l)
— Each operation traverses the word/prefix of length l. - 🧺 Space complexity:
O(n * l)
— n is the number of words, l is the average word length (for Trie storage).