DSA Trie

Implement Trie

Build a prefix tree supporting insert, search, and startsWith in O(L).

Medium
Time O(L) Space O(N * L)
LeetCode
5 min read
trie design

Problem#

Implement Trie with three operations:

  • insert(word) — add a string.
  • search(word) — return true iff word was inserted.
  • startsWith(prefix) — return true iff some inserted word has prefix as a prefix.

Examples#

  • Insert “apple”, search("apple")true, search("app")false, startsWith("app")true, insert “app”, search("app")true.

Constraints#

  • 1 <= word.length <= 2000, lowercase English letters.

Hints#

Hint
Each node has 26 children plus a “this is a word end” flag.

Approach#

Static array of 26 child pointers per node. insert walks/creates children for each character then flips isEnd on the last node. search returns true iff traversal succeeds and ends on a flagged node. startsWith is the same minus the flag check.

Solution#

Implement Trie
class Trie {
struct Node {
Node* child[26]{};
bool isEnd = false;
};
Node* root;
public:
Trie() : root(new Node()) {}
void insert(const string& word) {
Node* cur = root;
for (char c : word) {
int i = c - 'a';
if (!cur->child[i]) cur->child[i] = new Node();
cur = cur->child[i];
}
cur->isEnd = true;
}
bool search(const string& word) {
Node* n = find(word);
return n && n->isEnd;
}
bool startsWith(const string& prefix) {
return find(prefix) != nullptr;
}
private:
Node* find(const string& s) {
Node* cur = root;
for (char c : s) {
int i = c - 'a';
if (!cur->child[i]) return nullptr;
cur = cur->child[i];
}
return cur;
}
};

Editorial#

The 26-slot array is faster than a hash map for English alphabets — O(1) child lookups, dense memory, cache-friendly. isEnd distinguishes a stored word from an internal prefix. For larger alphabets or Unicode, switch the children to unordered_map<char, Node*>.

Complexity#

  • Time: O(L) per operation.
  • Space: O(N * L) worst case across inserted strings.

Concept revision#

Search ESC

Keyboard shortcuts

Shortcuts are disabled while typing in inputs.