Design Search Autocomplete System
Reported by candidates from Bloomberg's online assessment. Pattern, common pitfall, and the honest play if you blank under the timer.
Bloomberg reported this one in October 2025, and the detail that matters is the three-level tie-break: count, then earliest timestamp, then lexicographic order. It's the batch version of search autocomplete, and the hinted pattern is binary search, though a Trie or a sorted array both work. You get queries, timestamps and prefixes, and you return one ranked list per prefix. The empty prefix matches everything, and a prefix with no match returns an empty list. If you blank on the data structure during the live OA, StealthCoder is the invisible safety net that reads the problem and hands you a working approach.
The problem
You are given three arrays: queries[i] is a search query issued by a user. timestamps[i] is the time when queries[i] was issued. prefixes[j] is a prefix typed into an autocomplete box. For each prefix, return every distinct query that starts with that prefix, ordered by: Higher occurrence count first. If counts tie, smaller earliest timestamp first (the earliest time that query was ever issued). If both still tie, lexicographically smaller query first. Return one ranked list per prefix, in the same order as prefixes. If a prefix has no matching query, return an empty list for that prefix. The empty prefix matches every distinct query. This is the batch version of the classic search-autocomplete design question. A Trie keyed on query strings (each terminal node carrying the query's count and earliest timestamp) lets each prefix lookup collect its subtree's queries, which are then ranked by the comparator above. In a live interview, clarify whether the output should include all matching queries or only the top k suggestions. Function autocomplete(queries: String[], timestamps: int[], prefixes: String[]) → List<List<String>> Examples Example 1 queries = ["roblox studio", "roblox", "roadblocks", "roblox studio", "roblox game", "roblox"] timestamps = [5, 1, 7, 3, 4, 2] prefixes = ["rob", "robl", "road", "x"] return = [["roblox", "roblox studio", "roblox game"], ["roblox", "roblox studio", "roblox game"], ["roadblocks"], []] "roblox" and "roblox studio" each appear twice, so they rank ahead of "roblox game" (once). Between the two count-2 queries, "roblox" has earliest timestamp 1 versus "roblox studio" earliest timestamp 3, so "roblox" comes first. Prefixes "rob" and "robl" match the same three queries; "road" matches only "roadblocks"; "x" matches nothing. Example 2 queries = ["alpha", "alpine", "alpha", "alpine"] timestamps = [10, 3, 2, 8] prefixes = ["al"] return = [["alpha", "alpine"]] Both queries appear twice, so the earliest-timestamp tie-break applies: "alpha" has earliest timestamp 2 while "alpine" has earliest timestamp 3, so "alpha" ranks first. Example 3 queries = ["aba", "abb", "aba", "abb"] timestamps = [1, 1, 5, 7] prefixes = ["ab"] return = [["aba", "abb"]] Both queries appear twice and share earliest timestamp 1, so the lexicographic tie-break orders "aba" before "abb". Constraints queries.length == timestamps.length 0 <= queries.length <= 10^5 1 <= prefixes.length <= 10^4 1 <= queries[i].length <= 100 0 <= prefixes[i].length <= 100 0 <= timestamps[i] <= 10^9 queries[i] contains printable ASCII characters. prefixes[i] is empty or contains printable ASCII characters.
Reported by candidates. Source: FastPrep
Pattern and pitfall
First, aggregate. One pass with a hash map gives each distinct query its count and its minimum timestamp. Then sort the distinct queries once by the comparator: count descending, earliest timestamp ascending, string ascending. Once that global order is fixed, every prefix answer is just the matching queries in that order. Two clean routes. Route one: a Trie where each node stores the ranked list, or collect the subtree per prefix and sort. Route two: sort distinct queries alphabetically, binary search to the prefix range, then rank that slice. The pitfall is taking the earliest timestamp from the first occurrence in the array instead of the true minimum, since timestamps aren't sorted. Another is forgetting that the empty prefix returns every distinct query. Watch the cost too: 10^4 prefixes times a big subtree can blow up, so presort globally and filter in order. StealthCoder is your hedge if the comparator logic slips under pressure.
StealthCoder is the hedge for the one pattern you didn't drill. It runs invisibly during the screen share.
You can drill Design Search Autocomplete System cold, or you can hedge it. StealthCoder runs invisibly during screen share and surfaces a working solution in under 2 seconds. The proctor sees the IDE. They don't see what's behind it. If you're reading this with an OA window open, you're who this was built for.
Get StealthCoderRelated leaked OAs
You've seen the question.
Make sure you actually pass Bloomberg's OA.
Bloomberg reuses patterns across OAs. If you're reading this with an OA window open, you're who this was built for. Works on HackerRank, CodeSignal, CoderPad, and Karat.
Design Search Autocomplete System FAQ
What's the trick in the Bloomberg autocomplete OA?+
Aggregate first. Build a map of query to count and minimum timestamp, then sort the distinct queries once with the three-level comparator. After that, each prefix is a filter over an already ranked list. Don't re-sort per prefix unless you have to.
Is binary search actually required here?+
No, but it helps. Sort distinct queries alphabetically, binary search for the first string with the prefix, and scan until the prefix stops matching. A Trie also works. Pick whichever you can code without bugs in the time you have.
How do I handle the earliest timestamp correctly?+
Take the minimum timestamp seen across all occurrences of that query, not the first one in the array. The timestamps aren't sorted, and example 2 shows why: alpha appears at 10 and 2, so its earliest is 2.
What edge cases should I test?+
Empty prefix returns every distinct query. A prefix with no match returns an empty list. Empty queries array with prefixes still returns one empty list per prefix. Ties on both count and timestamp fall to lexicographic order, as in example 3.
How do I prepare for this in 48 hours?+
Code it once with a hash map plus sort, then once with a Trie. Practice writing the three-key comparator in your language without looking it up. Also ask whether the output is all matches or only top k, since the statement flags that ambiguity.