86. Design Add and Search Words Data Structure
mediumAsked at DatadogDesign a dictionary with addWord and search where '.' matches any letter. Datadog uses this for the Trie + DFS combo — same shape as their wildcard-tag-pattern lookup in the metric query layer.
By Alex Chen, Founder, InterviewChamp.AI · Last verified
Source citations
Public interview reports confirming this problem appears in Datadog loops.
- Glassdoor (2026-Q1)— Datadog onsite — wildcard-tag-pattern analog.
Problem
Design a data structure that supports adding new words and finding if a string matches any previously added string. Implement the WordDictionary class with addWord(word) and search(word). search(word) returns true if there is any string in the data structure that matches word. word may contain dots '.' where dots can be matched with any letter.
Constraints
1 <= word.length <= 25word in addWord consists of lowercase English letters.word in search consists of lowercase English letters and '.' characters.At most 10^4 calls.
Examples
Example 1
addWord('bad'), addWord('dad'), addWord('mad'), search('pad'), search('bad'), search('.ad'), search('b..')[null,null,null,false,true,true,true]Approaches
1. List of words + regex match
Store all words; on search, regex match each.
- Time
- search O(N * L)
- Space
- O(total chars)
// Store list; on search, for each word, check matches with the pattern.Tradeoff: O(N*L) per search — Datadog will push for Trie.
2. Trie + DFS for wildcards (optimal)
Insert into Trie as usual. On search with '.', recurse on ALL children at that level.
- Time
- addWord O(L), search O(L) avg / O(26^L) worst
- Space
- O(total chars)
class WordDictionary {
constructor() { this.root = { children: new Map(), isEnd: false }; }
addWord(word) {
let n = this.root;
for (const c of word) {
if (!n.children.has(c)) n.children.set(c, { children: new Map(), isEnd: false });
n = n.children.get(c);
}
n.isEnd = true;
}
search(word) {
function dfs(node, i) {
if (i === word.length) return node.isEnd;
const c = word[i];
if (c === '.') {
for (const child of node.children.values()) if (dfs(child, i + 1)) return true;
return false;
}
if (!node.children.has(c)) return false;
return dfs(node.children.get(c), i + 1);
}
return dfs(this.root, 0);
}
}Tradeoff: Trie + DFS branches on '.'. Worst case 26^L if all chars are '.' but practical cases are fast. Datadog-canonical wildcard query.
Datadog-specific tips
Datadog will probe with: 'How many '.'s before this gets slow?' Worst-case 26^L for all-wildcards; in practice constrained by ~25 chars. Articulate why this is acceptable: most searches have few wildcards.
Common mistakes
- Iterating Map.entries instead of Map.values for '.' branching — the keys aren't needed.
- Forgetting node.isEnd check on the last character — returns true for prefixes.
- Recursing on Set instead of Map — Set doesn't preserve mapping.
Follow-up questions
An interviewer at Datadog may pivot to one of these next:
- Implement Trie (LC 208) — base case.
- Word Search II (LC 212) — Trie + DFS on a board.
- Datadog-style: wildcard pattern over tag space.
Solve it now
Free. No sign-up. Python and JavaScript run instantly in your browser.
FAQ
Why DFS at '.'?
The wildcard could match any child. We must explore all branches to know if ANY leads to a valid completion.
Worst-case complexity?
If the search is all '.' (e.g. '....'), we explore every node up to depth L — that's O(26^L) in the worst case.
Practice these live with InterviewChamp.AI
Drill Design Add and Search Words Data Structure and other Datadog interview questions under real-loop conditions with instant feedback on your reasoning, complexity claims, and code.
Practice these live with InterviewChamp.AI →