Design Add and Search Words Data Structure - JS Solution

JS
Editorial

Solution explanation

Solution explanation

Approach

We implement a Trie-based dictionary that supports two operations: addWord(word) and search(word), where '.' can match any single character.

🧱 Trie Structure

  • Each node is a TrieNode with:
    • children: keeps track of all possible next nodes — each entry represents a character leading to the next step along a word’s path.
    • isEndOfWord: true if a complete word ends at this node.
  • Words are stored character by character along a path from the root, and shared prefixes reuse the same nodes.

✏️ addWord(word)

  • Start from root.
  • For each character c in word:
    • If children[c] does not exist, create a new TrieNode.
    • Move down to children[c].
  • After all characters are processed, mark the final node’s isEndOfWord = true.
  • This ensures the entire word is stored in the Trie as a path starting from the root and ending at an end-of-word node.

🔍 search(word) with '.' Wildcards

The helper _searchFromNode(word, node, index) examines the substring word[index..] starting from the given node. The main search begins with a call to _searchFromNode(word, root, 0), meaning it starts from the root node and the first character of the word. Inside the helper, a loop runs from the current index up to the end of the word, processing one character per step:

  • If the character is a wildcard ('.'):
    • '.' can match any single character at this position.
    • We iterate through all children of the current node and recursively call _searchFromNode(word, child, index + 1) for each of them.
    • If any recursive call returns true, we propagate true upward immediately.
    • If none succeed, return false.
  • Else if there is no child for the current character:
    • The path breaks — return false since the required child does not exist.
  • Else (child exists for the current character):
    • Move down to that child node and continue the loop with index + 1.

Once the loop finishes (i.e., index === word.length), we return the isEndOfWord flag of the current (terminal) node. It directly indicates whether the search ended on a complete word or only on a prefix.

🧠 Correctness Intuition

The Trie constrains the search to only those paths that match the query: normal characters follow a single exact child edge, while '.' triggers a controlled branching over all possible next characters at that position. By recursively exploring every valid continuation for wildcard positions and requiring the final node to be marked with isEndOfWord = true, any true result corresponds to an actual stored word that matches the pattern exactly.

Time Complexity

Let L be the length of the input word or search pattern.

  • addWord(word): O(L) — visiting one node per character, creating a new node only if it does not already exist.
  • search(word): O(L).

Although wildcard ('.') matching can in theory cause branching at each occurrence, here the number of wildcards is strictly limited (at most two per query). Each wildcard can substitute for any of the 26 lowercase letters, so at most 26 × 26 alternative paths are explored when both appear. This branching factor is a constant with respect to the word length. For each normal character, the algorithm linearly proceeds to the corresponding child (or stops traversal if the child is missing). Therefore, the maximum total number of visited nodes scales linearly with L.

Space Complexity

Let M be the total number of characters across all added words, and L the length of a single inserted word.

  • addWord(word): O(L) — in the worst case, a new node is created for each character if no prefix is shared with existing words.
  • Overall Trie storage: O(M) — total number of nodes across all inserted words, worst case happens when there is no shared prefix at all.

Each node contains a children mapping and a boolean flag isEndOfWord. These structures are constant in size per node, so they do not affect the asymptotic complexity.

Visucodize editorial solution titled JS Solution for LeetCode's Design Add and Search Words Data Structure coding problem. Includes code and may include explanation. You can animate the code step by step using the provided input by clicking the run button, or fork it locally to update the code and input for custom visualization. View the original problem at https://leetcode.com/problems/design-add-and-search-words-data-structure.