Bird
Raised Fist0
Interview Prepchallenge-problemshardAmazonFacebookGoogleMicrosoft

Find Median from Data Stream

Choose your preparation mode4 modes available
📋
Problem

Imagine you are monitoring live sensor data or stock prices and need to report the median value at any moment as new data arrives continuously.

Design a data structure that supports adding numbers from a data stream and finding the median of all elements so far. Implement two methods: addNum(int num) - adds a number to the data structure; findMedian() - returns the median of all elements added so far. The median is the middle value in an ordered integer list. If the size of the list is even, the median is the average of the two middle numbers.

1 ≤ number of addNum calls ≤ 10^5-10^5 ≤ num ≤ 10^5At least one element will be present before calling findMedian
Edge cases: Only one element added → median is that elementAll elements are the same → median is that elementLarge number of elements with duplicates → median calculation remains correct
</>
IDE
class MedianFinder: def __init__(self): pass def addNum(self, num: int) -> None: pass def findMedian(self) -> float: passpublic class MedianFinder { public MedianFinder() {} public void addNum(int num) {} public double findMedian() { return 0; } }class MedianFinder { public: MedianFinder() {} void addNum(int num) {} double findMedian() { return 0; } };class MedianFinder { constructor() {} addNum(num) {} findMedian() { return 0; } }
class MedianFinder:
    def __init__(self):
        # Write your solution here
        pass
    def addNum(self, num: int) -> None:
        pass
    def findMedian(self) -> float:
        pass
public class MedianFinder {
    public MedianFinder() {
        // Write your solution here
    }
    public void addNum(int num) {
    }
    public double findMedian() {
        return 0;
    }
}
#include <vector>
using namespace std;

class MedianFinder {
public:
    MedianFinder() {
        // Write your solution here
    }
    void addNum(int num) {
    }
    double findMedian() {
        return 0;
    }
};
class MedianFinder {
    constructor() {
        // Write your solution here
    }
    addNum(num) {
    }
    findMedian() {
        return 0;
    }
}
Coming soon
0/9
Common Bugs to Avoid
Wrong: Median values off by one or incorrect averagesNot balancing the two heaps properly after insertion✅ After each addNum, rebalance heaps so their sizes differ by at most one
Wrong: Median is always the last inserted element or first elementUsing a greedy approach that does not maintain order or balance✅ Use two heaps to maintain lower and upper halves and compute median from heap tops
Wrong: Median incorrect when duplicates are presentIgnoring duplicates or treating them as single elements✅ Insert all duplicates into heaps and balance normally
Wrong: TLE on large inputsSorting entire list on every addNum call✅ Implement two heaps approach for O(log n) insertion and O(1) median retrieval
Wrong: Median calculation causes integer overflow or wrong averagingUsing integer division or not using float/double for median✅ Use float/double type and compute average as (a + b) / 2.0
✓
Test Cases
t1_01basic
Input["addNum(1)","addNum(2)","findMedian()","addNum(3)","findMedian()"]
Expected[1.5,2]

After adding 1 and 2, the sorted list is [1,2], median is (1+2)/2=1.5. After adding 3, list is [1,2,3], median is 2.

t1_02basic
Input["addNum(5)","addNum(15)","addNum(1)","findMedian()","addNum(3)","findMedian()"]
Expected[5,4]

After adding 5,15,1 the sorted list is [1,5,15], median is 5. After adding 3, list is [1,3,5,15], median is (3+5)/2=4.

t2_01edge
Input["addNum(10)","findMedian()"]
Expected[10]

Only one element added, median is that element itself.

t2_02edge
Input["addNum(7)","addNum(7)","addNum(7)","findMedian()"]
Expected[7]

All elements are the same, median is that element.

t2_03edge
Input["addNum(-100000)","addNum(100000)","findMedian()"]
Expected[0]

Elements at boundary values, median is average of -100000 and 100000 = 0.

t3_01corner
Input["addNum(1)","addNum(2)","addNum(3)","addNum(4)","addNum(5)","findMedian()"]
Expected[3]

Sequential increasing numbers, median is middle element 3.

t3_02corner
Input["addNum(1)","addNum(1)","addNum(1)","addNum(1)","findMedian()"]
Expected[1]

Repeated identical elements, test for confusion between 0/1 knapsack style counting and median calculation.

t3_03corner
Input["addNum(100000)","addNum(-100000)","addNum(0)","addNum(99999)","addNum(-99999)","findMedian()"]
Expected[0]

Mixed large positive and negative numbers, median is 0 after sorting [-100000,-99999,0,99999,100000].

t4_01performance
Input["addNum(0)","addNum(1)","addNum(2)","addNum(3)","addNum(4)","addNum(5)","addNum(6)","addNum(7)","addNum(8)","addNum(9)","addNum(10)","addNum(11)","addNum(12)","addNum(13)","addNum(14)","addNum(15)","addNum(16)","addNum(17)","addNum(18)","addNum(19)","addNum(20)","addNum(21)","addNum(22)","addNum(23)","addNum(24)","addNum(25)","addNum(26)","addNum(27)","addNum(28)","addNum(29)","addNum(30)","addNum(31)","addNum(32)","addNum(33)","addNum(34)","addNum(35)","addNum(36)","addNum(37)","addNum(38)","addNum(39)","addNum(40)","addNum(41)","addNum(42)","addNum(43)","addNum(44)","addNum(45)","addNum(46)","addNum(47)","addNum(48)","addNum(49)","addNum(50)","addNum(51)","addNum(52)","addNum(53)","addNum(54)","addNum(55)","addNum(56)","addNum(57)","addNum(58)","addNum(59)","addNum(60)","addNum(61)","addNum(62)","addNum(63)","addNum(64)","addNum(65)","addNum(66)","addNum(67)","addNum(68)","addNum(69)","addNum(70)","addNum(71)","addNum(72)","addNum(73)","addNum(74)","addNum(75)","addNum(76)","addNum(77)","addNum(78)","addNum(79)","addNum(80)","addNum(81)","addNum(82)","addNum(83)","addNum(84)","addNum(85)","addNum(86)","addNum(87)","addNum(88)","addNum(89)","addNum(90)","addNum(91)","addNum(92)","addNum(93)","addNum(94)","addNum(95)","addNum(96)","addNum(97)","addNum(98)","addNum(99)","findMedian()"]
⏱ Performance - must finish in 2000ms

n=100 addNum calls followed by findMedian; O(log n) per addNum and O(1) findMedian must complete within 2 seconds.

Practice

(1/5)
1. Given the following Python code snippet implementing the AllOne data structure, what is the output of getMaxKey() after these operations?

all_one = AllOne() all_one.inc('apple') all_one.inc('banana') all_one.inc('apple') all_one.dec('banana') print(all_one.getMaxKey())
easy
A. "" (empty string)
B. "apple"
C. "banana"
D. Raises an exception

Solution

  1. Step 1: Trace increments and decrements

    After inc('apple') twice, 'apple' count = 2. 'banana' incremented once then decremented once, so removed.
  2. Step 2: Check getMaxKey()

    Max count bucket is 2 with 'apple'. So getMaxKey() returns 'apple'.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Only 'apple' remains with max count 2 [OK]
Hint: Max key is the one with highest count after updates [OK]
Common Mistakes:
  • Forgetting to remove 'banana' after dec to zero count
2. Given the following code snippet for the optimal Twitter design, what is the output of getNewsFeed(1) after these operations?
twitter = Twitter()
twitter.postTweet(1, 5)
twitter.postTweet(2, 6)
twitter.followees[1] = {2}
print(twitter.getNewsFeed(1))
Assume getNewsFeed returns a list of tweetIds sorted from most recent to oldest.
easy
A. [6]
B. [5, 6]
C. [5]
D. [6, 5]

Solution

  1. Step 1: Trace postTweet calls

    User 1 posts tweet 5 at time=1, user 2 posts tweet 6 at time=2.
  2. Step 2: Trace getNewsFeed(1)

    User 1 follows user 2, so heap contains tweets with times 1 (tweet 5) and 2 (tweet 6). Max heap pops tweet 6 first, then tweet 5.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Heap orders tweets by descending time, so output is [6, 5] [OK]
Hint: Heap orders tweets by negative time for max behavior [OK]
Common Mistakes:
  • Returning tweets in posting order instead of time order
  • Ignoring followees' tweets
3. You need to design a cache that evicts the least frequently used item when full, and among items with the same frequency, evicts the least recently used one. Which approach guarantees O(1) average time complexity for both get and put operations?
easy
A. Using a simple hash map with frequency counts and sorting keys on each eviction
B. Maintaining a frequency map of doubly linked lists to track keys by frequency and recency
C. Using a min-heap keyed by frequency and timestamp to evict the least frequently used item
D. Using a single doubly linked list ordered by frequency and recency

Solution

  1. Step 1: Understand the eviction criteria

    The cache must evict the least frequently used key, and if multiple keys share the same frequency, evict the least recently used among them.
  2. Step 2: Identify data structures supporting O(1) operations

    A frequency map with doubly linked lists allows grouping keys by frequency and maintaining recency order within each frequency group, enabling O(1) updates and eviction.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Frequency map + doubly linked lists is the classic LFU O(1) approach [OK]
Hint: Frequency map + doubly linked lists enable O(1) LFU cache [OK]
Common Mistakes:
  • Using sorting on eviction is too slow
  • Min-heap adds O(log n) overhead
  • Single list can't maintain frequency and recency efficiently
4. Consider the following buggy code snippet for merging two skylines. Which line contains the subtle bug that can cause incorrect skyline output?
medium
A. Line where merged.append([x, max_h]) is called unconditionally
B. Line where x, h1 = left[i] inside first if
C. Line where max_h is computed with max(h1, h2)
D. Line where i and j are incremented in the else block

Solution

  1. Step 1: Identify difference from correct code

    The bug is that merged.append is called every iteration without checking if height changed, causing redundant points.
  2. Step 2: Understand impact of redundant points

    Appending points even when max_h equals previous height leads to unnecessary key points, failing correctness checks.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Correct code appends only if height changes [OK]
Hint: Appending only on height change avoids redundant points [OK]
Common Mistakes:
  • Appending every iteration regardless of height change
  • Incorrect pointer increments
5. Suppose the skyline problem is extended so that buildings can overlap and have negative heights (e.g., representing underground structures). Which modification to the divide and conquer approach is necessary to correctly handle this variant?
hard
A. Modify the merge step to consider absolute values of heights when computing max height
B. Adjust the merge logic to track both max and min heights at each x-coordinate and merge accordingly
C. No modification needed; the existing merge logic works for negative heights
D. Replace divide and conquer with a brute force height map simulation to handle negative heights

Solution

  1. Step 1: Understand impact of negative heights

    Negative heights mean skyline can go below ground, so max height alone is insufficient to represent shape.
  2. Step 2: Modify merge logic accordingly

    Need to track both max and min heights at each x to correctly merge skylines with negative and positive heights.
  3. Step 3: Evaluate other options

    Using absolute values loses sign info; brute force is inefficient; no modification fails correctness.
  4. Final Answer:

    Option B -> Option B
  5. Quick Check:

    Tracking both max and min heights handles negative overlaps correctly [OK]
Hint: Negative heights require tracking min and max heights, not just max [OK]
Common Mistakes:
  • Ignoring negative heights
  • Using absolute values incorrectly
  • Assuming no change needed
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard