Arrays, Hashing & Heaps
- Clear the array and string screens that open the Okta loop: prefix/suffix products, and the talk-through-first expectation
- Build Insert Delete GetRandom O(1) with a value-to-indices map and swap-with-last removal
- Solve Find Median from a Data Stream with two balanced heaps, the most-repeated Okta coding problem
- Use a bounded heap to rank users by score, and know the follow-ups each problem invites
Okta's coding rounds run practical, but the first screen and one or two onsite rounds still lean on the array, hashing, and heap staples every backend loop shares. The problems that recur are not obscure. Each fits in a sentence: reshape an array without division, build a container whose every operation is O(1), keep a running median as numbers stream in, rank users by score. An interviewer can pose one, watch you talk it through, then push with a follow-up.
The through-line is that Okta grades the conversation as much as the code. Interviewers here expect you to state the approach, name the data structure, and reason about complexity before you type, then write a full working solution with the edge cases covered. A correct answer delivered silently reads worse than a slightly slower one you narrated cleanly. The four most-reported problems from this family follow, each drilled end to end with the follow-up Okta tends to add next.
How Okta frames it
Three framings show up repeatedly. The pure screen is a standard easy-to-medium problem that wants a clean optimal solution and a crisp complexity argument. Product of Array Except Self, paired with a graph problem, is a reported first-round set. The design-with-hashing problem asks you to build a small container to a contract. The trick is picking the right pair of structures so every operation stays O(1). Insert Delete GetRandom is the canonical one, and it has opened a staff loop. The data-stream problem hands you numbers one at a time and asks for an answer maintained on the fly, which is where heaps earn their place. Find Median from a Data Stream is the most-repeated named problem in the Okta coding rounds, and it has been asked as a full staff round on its own.
Expect the follow-up before you finish the original. Okta interviewers rarely stop at the first working solution. Product invites "now do it without division," and the median stream invites "what if every value is between 0 and 100." The ranking problem invites "now rank by total, and stream it." Solve the base cleanly, then have the escalation ready.
The three moves to know
Each of the four problems below is really one of three reusable moves. Learn the move and the specific problem falls out of it.
Move 1: the prefix/suffix sweep
When each output slot depends on everything to its left and everything to its right, two passes beat any nested loop. Sweep left carrying the running result of everything before i, then sweep right carrying everything after it, and combine. Nothing between the two ends is ever recomputed.
answer = [1] * nprefix = 1for i in range(n): # everything strictly LEFT of i answer[i] = prefix prefix *= nums[i]suffix = 1for i in range(n - 1, -1, -1): # everything strictly RIGHT of i answer[i] *= suffix suffix *= nums[i]Move 2: the value-to-index map with swap-remove
To make insert, remove, and random access all O(1), store the values in a flat array, so a random pick is one index lookup. Add a hash map from each value to where it lives in that array, so remove is a lookup instead of a scan. The one trick that makes remove O(1) is to overwrite the removed slot with the last element and shrink the array, then repair the moved element's recorded index. No shifting.
The array gives you O(1) uniform random access; the map gives you O(1) locate-and-delete. Deleting from the middle of an array is normally O(n) because everything shifts, so you never delete from the middle: you swap the target with the last element and pop the end.
Move 3: two balanced heaps
To track the middle of a stream, split the numbers into a lower half and an upper half. Keep the lower half in a max-heap (its top is the largest small number) and the upper half in a min-heap (its top is the smallest large number). Keep their sizes within one of each other, and the median is either the larger heap's top or the average of the two tops. Every insert is a couple of heap operations; the median is a peek.
Asked at Okta
These are the array, hashing, and heap problems reported most often across Okta's screens and onsite coding rounds. Build each until the approach, the edge cases, and the follow-up are automatic.
Find Median from Data Stream: Two Balanced Heaps
Problem
Implement
MedianFinder:-
addNum(num) ingests one number from the stream.-
findMedian() returns the median of all numbers added so far.Both operations must be efficient enough to interleave freely over a long stream.
Input: addNum(1), addNum(2), findMedian()
Output: 1.5
Two numbers, so the median is their average.
Input: ...then addNum(3), findMedian()
Output: 2.0
Now [1,2,3], so the middle value is 2.
Keep a max-heap of the smaller half and a min-heap of the larger half, sizes within one. The median reads off the heap tops in O(1); each insert is O(log n).
Find Median from Data Stream: Two Balanced Heaps
Click "Run" to execute your code
Test Cases
[["MedianFinder",[]],["addNum",[1]],["addNum",[2]],["findMedian",[]],["addNum",[3]],["findMedian",[]]]Expected: [null,null,null,1.5,null,2.0][["MedianFinder",[]],["addNum",[6]],["findMedian",[]],["addNum",[10]],["addNum",[2]],["findMedian",[]]]Expected: [null,null,6.0,null,null,6.0][["MedianFinder",[]],["addNum",[5]],["addNum",[5]],["addNum",[5]],["addNum",[5]],["findMedian",[]]]Expected: [null,null,null,null,null,5.0]Product of Array Except Self: Prefix/Suffix Sweep
Problem
nums, return an array answer where answer[i] is the product of every element of nums except nums[i].You must solve it without using the division operator, and the intended solution runs in O(n) time. The array may contain zeros and negative numbers.
Input: nums = [1,2,3,4]
Output: [24,12,8,6]
answer[0] = 2*3*4 = 24, answer[1] = 1*3*4 = 12, and so on.
Input: nums = [-1,1,0,-3,3]
Output: [0,0,9,0,0]
Only the slot holding the single zero gets a non-zero product; every other slot multiplies in that zero.
Two passes: one accumulating the product of everything to the left of each index, one accumulating everything to the right, multiplied together.
Product of Array Except Self: Prefix/Suffix Sweep
Click "Run" to execute your code
Test Cases
[[1,2,3,4]]Expected: [24,12,8,6][[-1,1,0,-3,3]]Expected: [0,0,9,0,0][[2,3]]Expected: [3,2][[0,0,5]]Expected: [0,0,0]total / nums[i] a divide-by-zero, and two or more zeros make every answer zero. The clean division solution counts zeros first, then branches.Insert Delete GetRandom O(1): Duplicates Allowed
Problem
Implement
RandomizedCollection:-
insert(val) adds one occurrence of val and returns true if val was not already present, false otherwise.-
remove(val) removes one occurrence of val if present and returns whether anything was removed.-
getRandom() returns an element chosen uniformly at random from the current multiset, so a value stored three times is three times as likely to be returned.Input: insert(1), insert(1), insert(2), remove(1), getRandom()
Output: true, false, true, true, then 1 or 2
After the removes the collection holds one 1 and one 2, so getRandom returns each with probability 1/2.
Keep a flat list of values for O(1) random access, plus a map from each value to the SET of indices where it currently lives. Remove by swapping the target with the last element.
Insert Delete GetRandom O(1): Duplicates Allowed
Click "Run" to execute your code
Test Cases
[["RandomizedCollection",[]],["insert",[1]],["insert",[1]],["insert",[2]],["remove",[1]],["insert",[3]],["remove",[2]]]Expected: [null,true,false,true,true,true,true][["RandomizedCollection",[]],["insert",[5]],["insert",[5]],["remove",[5]],["remove",[5]],["remove",[5]]]Expected: [null,true,false,true,true,false][["RandomizedCollection",[]],["remove",[9]],["insert",[9]],["remove",[9]],["remove",[9]]]Expected: [null,false,true,true,false]Top Users by Score: Bounded Heap Selection
Problem
[userId, score]. A user may appear many times. Return the k users with the highest single best score, ordered from highest to lowest. Break ties between equal best scores by smaller userId first.If a user posts several scores, only their maximum counts toward the ranking.
Input: events = [[1,50],[2,80],[1,90],[3,70],[2,60]], k = 2
Output: [1,2]
Best scores are user 1 -> 90, user 2 -> 80, user 3 -> 70. The top two are users 1 and 2.
Input: events = [[1,90],[2,90],[3,50]], k = 2
Output: [1,2]
Users 1 and 2 tie at 90; the smaller id (1) ranks first.
Reduce to each user's best score in a hash map, then use a size-k min-heap to keep only the top k without sorting everyone.
Top Users by Score: Bounded Heap Selection
Click "Run" to execute your code
Test Cases
[[[1,50],[2,80],[1,90],[3,70],[2,60]], 2]Expected: [1,2][[[1,90],[2,90],[3,50]], 2]Expected: [1,2][[[7,10],[8,40],[9,40],[7,55]], 2]Expected: [7,8][[[4,20]], 3]Expected: [4]Key Takeaways
- ✓Okta grades the talk-through: name the data structure and the complexity before you type, and write a full working solution with edge cases, not a silent optimal one.
- ✓Product of Array Except Self is a two-pass prefix/suffix sweep with no division; the escalation is handling zeros once division is allowed.
- ✓Insert Delete GetRandom pairs a flat array (for uniform random) with a value-to-indices map (for O(1) locate), and removes by swapping with the last element.
- ✓Find Median from a Data Stream is the most-repeated Okta coding problem: two balanced heaps put the median at the tops; a bounded value range unlocks the O(1)-insert counting solution.
Okta interview guideKnow what Okta asks before you walk in.
13 coding · 3 system design · 42 behavioral questions
Get their questions first.
InterviewLegend is independent and not affiliated with or endorsed by any company it covers.