Problem Statement
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.
Approach
1️⃣ To insert a Node in The Trie:
- Begin at the root node.
- For each character in the word:
- Check if the current node has a child node for the character.
- If the child node doesn't exist, create a new node and link it to the current node.
- Move to the child node that corresponds to the character.
- After inserting all characters, mark the end of the word by setting the end flag of the last node to true.
2️⃣ To Search for a word in Trie:
- Begin at the root node.
- For each character in the word:
- Verify if the current node has a child node for the character.
- If not, the word is not present in the Trie.
- Move to the child node corresponding to the character.
- After processing all characters, check if the end flag of the last node is set to true. If it is, the word is found; if not, the word is not in the Trie.
3️⃣ Check if Trie contains Prefix:
- Begin at the root node.
- For each character in the prefix:
- Check if the current node has a child node for the character.
- If it doesn't, there is no word with the given prefix.
- Move to the child node that corresponds to the character.
- If all characters of the prefix are found, return true to indicate that there are words with the given prefix.
Code in C++:
class TrieNode {
public:
TrieNode* children[26]; // Array to store pointers to child nodes (assuming only lowercase English letters)
bool isEndOfWord; // Indicates whether this node represents the end of a word
// Constructor: Initialize children to nullptr and isEndOfWord to false
TrieNode() {
isEndOfWord = false;
for (int i = 0; i < 26; i++) {
children[i] = nullptr;
}
}
};
class Trie {
private:
TrieNode* root; // Root node of the trie
public:
// Constructor: Initialize the trie with a root node
Trie() {
root = new TrieNode();
}
// Function to insert a word into the trie
void insert(string word) {
TrieNode* node = root; // Start from the root
for (char ch : word) { // Iterate through each character in the word
int index = ch - 'a'; // Calculate index in children array (0 for 'a', 1 for 'b', etc.)
if (node->children[index] == nullptr) { // If no node exists for the current character
node->children[index] = new TrieNode(); // Create a new node
}
node = node->children[index]; // Move to the child node
}
node->isEndOfWord = true; // Mark the last node as the end of a word
}
// Function to search for a word in the trie
bool search(string word) {
TrieNode* node = root; // Start from the root
for (char ch : word) { // Iterate through each character in the word
int index = ch - 'a'; // Calculate index in children array
if (node->children[index] == nullptr) { // If the path for the current character doesn't exist
return false; // The word is not in the trie
}
node = node->children[index]; // Move to the child node
}
return node->isEndOfWord; // Return true if the word ends at the current node
}
// Function to check if any word starts with the given prefix
bool startsWith(string prefix) {
TrieNode* node = root; // Start from the root
for (char ch : prefix) { // Iterate through each character in the prefix
int index = ch - 'a'; // Calculate index in children array
if (node->children[index] == nullptr) { // If the path for the current character doesn't exist
return false; // No word with the given prefix
}
node = node->children[index]; // Move to the child node
}
return true; // Return true if the prefix exists in the trie
}
};
Complexity Analysis:
- Time Complexity:
- Insertion:
O(N)
, where N is the length of the word being inserted. This is because we need to go through each letter of the word to either find its corresponding node or create a new node as needed. - Search:
O(N)
, where N is the length of the word being searched for. During a Trie search, we traverse each letter of the word starting from the root, checking if the current node has a child node at the position of the next letter. This continues until we either reach the end of the word or find a missing letter node. - Prefix Search:
O(N)
, where N is the length of the prefix being searched for. Just like in word search, we go through each letter of the prefix to find its corresponding node.
- Insertion:
- Space Complexity:
O(N)
where N is the total number of characters across all unique words inserted into the Trie. For each character in a word, a new node might need to be created, resulting in space usage that is proportional to the total number of characters.