InterviewLegend

Arrays, Strings & Hashing

Alex Chen15 min readUpdated 276 real interview reports
In this lesson
  • Prep the hash-table, array, and string cluster that leads MongoDB coding rounds by a wide margin
  • Write for the bar MongoDB grades: working, edge-case-correct, tested code before the optimal Big-O
  • Spot the follow-ups MongoDB adds, from a cheaper key to "now make it thread-safe"

MongoDB's coding rounds begin where the product does: with keys, and the values hanging off them. Look at which problems recur most in candidate reports and the public tagged set, and the top of the list is a run of hash-table, array, and string problems. This is a hashing-and-arrays loop first. Graphs and dynamic programming show up, but the center of gravity sits here, so this is the cluster to over-prepare rather than skim.

The problems themselves read like standard easy-to-medium fare. Group anagrams, compress a string in place, find a target in a rotated array, take the intersection of two arrays. What separates a MongoDB pass from a miss is rarely the algorithm. It is whether the code runs, holds up on the empty input and the single-element input and the all-duplicates input, and whether you tested it before saying you were done. MongoDB's own engineering-interview prep page names the axes it grades on, and edge-case correctness, object-oriented structure, and testing your own code sit right next to raw problem-solving.

The MongoDB angle
MongoDB grades working, edge-case-correct code above the fastest possible Big-O. Interviewers here are explicit that they would rather see a solution that runs and handles the corners than a clever one-liner that is close. Get a correct version on the screen, run it against the examples, then say out loud which edges you are about to check: empty input, one element, all-identical elements, values that repeat. Walking those cases before the interviewer prompts you is the single behavior that most separates the candidates who pass this loop. The optimization conversation comes after there is something correct to optimize.
  • Center of mass: Hash, array, string. Both the tagged problem set and firsthand reports put hash-table, array, and string problems at the top. Medium-centered with a real Hard tail. This is the cluster that shows up in almost every loop.
  • Where it runs: A live editor. Screens run on a shared editor that executes your code, often through the Karat vendor for early-career loops. Onsite coding runs live too. Whiteboard-only pseudocode does not clear the bar; the code is meant to run.
  • What is graded: Runs, edges, tests. From MongoDB's own prep page: language fluency, concurrency-safe code, edge cases, clean OOD, run-time-versus-memory trade-offs, and testing your own code. Correctness and structure lead; optimal complexity follows.
  • The concurrency tail: "Now make it safe". MongoDB is a concurrent database, so an otherwise standard problem often grows a "handle concurrent readers and writers" follow-up. The thread-safety round has its own lesson; expect its shadow even here.

The three shapes that cover this cluster

Almost everything in this band is one of three shapes. Learn the trigger for each, the structure it wants, and the MongoDB tail that tends to follow.

Hashing and bucketing by a computed key

The dominant shape collapses a nested rescan into a single pass by remembering what you have already seen, keyed on something you compute per element. Intersection of Two Arrays drops one array into a hash set and probes it with the other. Group Anagrams derives a canonical key per word so anagrams land in the same bucket. Kth Largest and the frequency problems count into a map first, then read the map. The instinct is the same one a database index runs on: turn "scan everything looking for a match" into "compute a key, jump straight to the bucket." When you can name the key that makes the lookup O(1), you have usually found the solution.

The MongoDB angle
Bucketing by a derived key is the same move MongoDB's aggregation pipeline makes when it groups documents. A $group stage keys each document on a computed field and accumulates the matches, exactly what a hash-grouping solution does with a dictionary of lists. Naming that connection is not just flavor; it signals you understand why the hash approach is the natural one and not a trick. When an interviewer pushes on "what if the input does not fit in memory," the honest answer borrows from the same world. You spill buckets to disk or partition by the key, the way a real grouping engine handles a dataset larger than RAM.

Two pointers and in-place rewriting

The second shape walks an array or string with a small number of indices and rewrites it in place instead of allocating a copy. Move Zeroes keeps a write pointer for the next non-zero slot while a read pointer scans ahead. String Compression counts each run of a character, then writes the character and its count back into the same buffer. The discipline that MongoDB grades hardest lives here. A run of length ten becomes two digit characters, a run of length one writes no count at all, and the write pointer must never overtake the read pointer. These are exactly the corners that separate code that looks right from code that is right, and this shape is where the "did you test it" axis earns its weight.

The third shape halves the search space each step by comparing against the middle. Search in Rotated Sorted Array is the recurring one: the array is sorted but wrapped around a pivot. On each step you first decide which half is properly sorted, then check whether the target falls inside that half. This is close to how a lookup walks a B-tree index page. The keys on a page are ordered, and the engine binary-searches within the page and then descends to the child that must contain the key rather than scanning. Getting the boundary comparisons right, and knowing what breaks when the array can hold duplicate values, is the whole game.

All three shapes trade a full scan for a jump. Hashing jumps to a bucket by a computed key, binary search jumps past half the array by an ordering, and the in-place two-pointer avoids a second pass by rewriting as it reads. That is the same bargain a database index strikes against a collection scan: pay a little to organize the data, then answer each query without touching most of it. When a MongoDB interviewer asks "can this be faster," the answer is almost always "what can I precompute or order so I stop rescanning."

Asked at MongoDB

Four problems cover the three shapes: two hashing problems, one in-place rewrite and one rotated binary search. Each test case is the function's arguments as a JSON array and the expected return. Write the base version in the editor and run it against the corners before you read the walkthrough, which carries the MongoDB follow-up the rest of the way.

The band's three Hard problems, three Premium questions, continue in Parsing, Text Layout & Sliding Windows.

1

Group Anagrams: Bucket by a Canonical Key

MediumFrequently asked
Problem
Given an array of strings strs, group the strings that are anagrams of one another. Two strings are anagrams when one is a rearrangement of the other, using every letter the same number of times.

To keep the answer deterministic, return the groups in a canonical order: sort the words inside each group, then sort the groups themselves. All inputs are lowercase letters or the empty string.

Input encoding. Each test case is a JSON array [strs], a single list of strings. The function returns a list of lists of strings.

Input: strs = ["eat","tea","tan","ate","nat","bat"]

Output: [["ate","eat","tea"],["bat"],["nat","tan"]]

eat, tea, and ate share the letters a,e,t; tan and nat share a,n,t; bat is alone.

Input: strs = [""]

Output: [[""]]

The empty string forms its own group.

Input: strs = ["a"]

Output: [["a"]]

A single word is a group of one.

How this uses the pattern

Compute one key per word that is identical for anagrams, and collect words into a dictionary of lists keyed on it. Sorting the letters of a word gives such a key.

Group Anagrams: Bucket by a Canonical Key

Loading...
Click "Run" to execute your code

Test Cases

Input: [["eat","tea","tan","ate","nat","bat"]]Expected: [["ate","eat","tea"],["bat"],["nat","tan"]]
Input: [[""]]Expected: [[""]]
Input: [["a"]]Expected: [["a"]]
Input: [["abc","bca","cab","xyz"]]Expected: [["abc","bca","cab"],["xyz"]]
Input: [["listen","silent","enlist","google","gogole"]]Expected: [["enlist","listen","silent"],["gogole","google"]]
Input: [["ab","ba","abc"]]Expected: [["ab","ba"],["abc"]]
Input: [["cinema","iceman","dog"]]Expected: [["cinema","iceman"],["dog"]]
The MongoDB angle
The cleanest test of the hashing instinct MongoDB leans on, and a direct analog of a $group aggregation stage keying documents on a derived field. The trap is choosing a key that is stable across anagrams: a plain set of letters loses duplicate counts, so "aab" and "abb" would wrongly collide. The sorted-letters string, or a 26-count vector, is the honest fingerprint. Getting the empty-string and single-word cases right is the edge-case discipline the loop grades.
Take it further
The natural push is cost. Sorting every word to build the key costs O(k log k) per word of length k. When words are long, swap the sorted-string key for a 26-entry letter-count vector, which builds the key in O(k) and drops the log factor entirely while grouping identically.
2

String Compression: Run-Length in the Buffer

MediumCommonly asked
Problem
Given a list of characters chars, compress it using run-length encoding. For each maximal run of a repeated character, write the character once, followed by the run length only when that length is 2 or more. A run of length 1 writes just the character with no count.

Return the compressed text as a string. A run whose length has multiple digits, such as 12, contributes each digit as a separate character (a12), which is what makes the edge cases interesting.

Input encoding. Each test case is a JSON array [chars], a single list of single-character strings. The function returns the compressed string.

Input: chars = ["a","a","b","c","c","c","c","c","a","a","a"]

Output: "a2bc5a3"

aa becomes a2, single b stays b, ccccc becomes c5, aaa becomes a3.

Input: chars = ["a","b","c"]

Output: "abc"

Every run has length 1, so no counts are written.

Input: chars = ["a","a","a","a","a","a","a","a","a","a","a","a"]

Output: "a12"

A run of twelve writes the character then the two digits 1 and 2.

How this uses the pattern

Scan the array once. Extend a run while the next character matches, then write the character and, only when the run exceeds 1, the digits of its length.

String Compression: Run-Length in the Buffer

Loading...
Click "Run" to execute your code

Test Cases

Input: [["a","a","b","c","c","c","c","c","a","a","a"]]Expected: "a2bc5a3"
Input: [["a","b","c"]]Expected: "abc"
Input: [["a"]]Expected: "a"
Input: [["a","a","a","a","a","a","a","a","a","a","a","a"]]Expected: "a12"
Input: [["a","a","b","b","c","c"]]Expected: "a2b2c2"
Input: [["a","a","a","b","b","a","a","c","c","c"]]Expected: "a3b2a2c3"
Input: [[]]Expected: ""
The MongoDB angle
A short problem that is almost entirely edge cases, which is exactly the axis MongoDB grades hardest. The count of a long run spans several characters, a run of one writes no count, and an empty input returns nothing. Interviewers here care that this runs correctly on all of those before they care that it is elegant. Run-length encoding is also the family of compression a storage engine reaches for on repetitive data, so the shape is domain-native rather than arbitrary.
Take it further
The real interview push is space. The base returns a fresh string, but the classic ask is to compress the character array in place and return the new length, using only constant extra space. A write pointer trails behind the read scan and overwrites the buffer as it consumes it, since the compressed form is never longer than the original.
3

Search in Rotated Sorted Array: Which Half Is Sorted

MediumCommonly asked
Problem
An array nums of distinct integers was sorted ascending, then rotated at an unknown pivot, so [0,1,2,4,5,6,7] might arrive as [4,5,6,7,0,1,2]. Given nums and a target, return the index of target, or -1 if it is absent. Aim for O(log n) time.

Input encoding. Each test case is a JSON array [nums, target]. The function returns the index as an integer, or -1.

Input: nums = [4,5,6,7,0,1,2], target = 0

Output: 4

0 sits at index 4 in the rotated array.

Input: nums = [4,5,6,7,0,1,2], target = 3

Output: -1

3 is not present.

Input: nums = [1], target = 0

Output: -1

A single element that is not the target.

How this uses the pattern

Binary search, but at each step first decide which half is properly sorted by comparing the low end to the middle, then check whether the target lies within that sorted half.

Search in Rotated Sorted Array: Which Half Is Sorted

Loading...
Click "Run" to execute your code

Test Cases

Input: [[4,5,6,7,0,1,2], 0]Expected: 4
Input: [[4,5,6,7,0,1,2], 3]Expected: -1
Input: [[1], 0]Expected: -1
Input: [[1], 1]Expected: 0
Input: [[5,1,3], 5]Expected: 0
Input: [[6,7,8,1,2,3,4,5], 8]Expected: 2
Input: [[1,3], 3]Expected: 1
The MongoDB angle
Binary search on data that is ordered but wrapped, which is close to how an index lookup binary-searches the ordered keys on a B-tree page before descending. The subtlety is that one half of the array is always properly sorted while the other holds the rotation seam. So each step first identifies the sorted half, then decides where the target can be. The boundary comparisons, and what changes once duplicates are allowed, are what the interviewer probes.
Take it further
The standard escalation allows duplicate values. Once nums can repeat, the low, middle, and high elements can all be equal, and you can no longer tell which half is sorted. The fix inspects that ambiguous case and shrinks both ends by one, which reintroduces a linear worst case but keeps every other step logarithmic.
4

Intersection of Two Arrays: Hash the Smaller Side

EasySignature problem
Problem
Given two integer arrays nums1 and nums2, return the values that appear in both. Each shared value appears once in the result, however many times it occurs on either side.

Return the result sorted ascending so the answer is comparable against one fixed expected value. Either array may be empty, and values may be negative.

Input encoding. Each test case is a JSON array [nums1, nums2]. The function returns a list of integers.

Input: nums1 = [1,2,2,1], nums2 = [2,2]

Output: [2]

Only 2 is shared. Four chances to emit it collapse to one entry.

Input: nums1 = [4,9,5], nums2 = [9,4,9,8,4]

Output: [4,9]

4 and 9 are shared; 5 and 8 are not. Ascending order puts 4 first.

Input: nums1 = [], nums2 = [1,2,3]

Output: []

An empty side shares nothing, so the answer is the empty list.

How this uses the pattern

Put the shorter array's values into a hash set, then walk the longer array and keep whatever the set contains. Removing a value from the set as you match it keeps the result free of repeats.

Intersection of Two Arrays: Hash the Smaller Side

Loading...
Click "Run" to execute your code

Test Cases

Input: [[1,2,2,1], [2,2]]Expected: [2]
Input: [[4,9,5], [9,4,9,8,4]]Expected: [4,9]
Input: [[], [1,2,3]]Expected: []
Input: [[1,2,3], []]Expected: []
Input: [[1,1,1], [1,1]]Expected: [1]
Input: [[1,2,3], [4,5,6]]Expected: []
Input: [[7], [7]]Expected: [7]
Input: [[5,3,1,3,5], [3,5,9]]Expected: [3,5]
Input: [[-4,0,2,-4], [2,-4,-4,11]]Expected: [-4,2]
Input: [[1,2,3,4,5,6,7,8], [8,1]]Expected: [1,8]
The MongoDB angle
MongoDB ships this operation as $setIntersection, an aggregation operator that treats its array arguments as sets, which is why repeats on either side collapse to a single entry. The sharper hook sits in the query planner. A query carrying two predicates, each covered by its own index, can be answered by scanning both indexes and intersecting the record ids they return instead of fetching documents for either one. A hash-based intersection builds its lookup table from the side it expects to be smaller and streams the other side past it, since the table is the part that has to sit in memory. Choosing the build side on purpose instead of always hashing nums1 is worth a sentence out loud.
Take it further
The escalation that follows takes the hash away. Suppose both arrays arrive sorted ascending, which is the shape an index scan hands you. Then two pointers walk them forward in lockstep, advancing whichever side is behind and emitting a value where they meet, with no table at all. Spend ten seconds asking out loud whether the inputs are sorted, because the answer moves the memory from O(min(n, m)) down to the output alone.

Key Takeaways

  • ✓This is the cluster to over-prepare. Hash-table, array, and string problems lead MongoDB coding rounds, running live on an editor that executes your code, often through the Karat vendor on early-career screens.
  • ✓Write for the bar MongoDB names on its own prep page: working, edge-case-correct, tested code before the optimal Big-O. Say which corners you are checking, empty and single-element and all-duplicate inputs, and check them before claiming you are done.
  • ✓Three shapes cover the band: bucket by a computed key, rewrite in place with two pointers, and binary-search ordered-but-rotated data. Each trades a full scan for a jump, the same bargain an index strikes against a collection scan.
  • ✓Expect the MongoDB tail. A clean solution grows a follow-up: drop the per-word sort, compress in place for constant space, or handle duplicates. Three Premium questions, the band's Hard problems, come next.
Had your MongoDB interview?Tell us what they asked. Reviewed before it goes in, never with your name.
MongoDB interview guide

Know what MongoDB asks before you walk in.

31 coding · 5 system design · 15 behavioral questions

Get Premium$49 a year · Cancel anytime
Or start freeNo card.

Get their questions first.

InterviewLegend is independent and not affiliated with or endorsed by any company it covers.