Hello, reader ๐๐ฝ ! Welcome to day 42 of the series on Problem Solving. Through this series, I aim to pick up at least one question everyday and share my approach for solving it.
Today, I will be picking up LeetCode's daily challenge problem: 295. Find Median from Data Stream.
๐ค Problem Statement
Implement the
MedianFinder
class:MedianFinder()
initializes theMedianFinder
object.void addNum(int num)
adds the integer num from the data stream to the data structure. -double findMedian()
returns the median of all elements so far. Answers within 10-5 of the actual answer will be accepted.
E.g.:
nums = [1,1,2]
=>2
nums = [0,0,1,1,1,2,2,3,3,4]
=>5
nums = [2,3,4]
=>3
๐ฌ Thought Process - Priority Queue
- One of the naive ways to solve is to use a list and maintain the list sorted. But then every time a new value is added sorting would take
O(n logn)
which is inefficient. - Hence we can make use of a priority queue to bring down the complexity to
O(logn)
. - The idea is to split the data into two halves using priority queues. The first half is stored in a max heap and the second half in a min heap.
- We also ensure that all the values in the max heap are less than every value in the min heap.
- Moreover at every insertion in the heaps, we ensure that the sizes of the two heaps differ no longer by one (for odd values) or are equal (even values).
- If we maintain this, then for the median operation, we will have three choices:
- The max heap size is greater than the min heap size.
- Then we return the front value from the max heap.
- The min heap size is greater than the max heap size.
- Then we return the front value from the min heap.
- Both the heaps are of equal size.
- Then we return the average of the front of the max and min heap.
- The max heap size is greater than the min heap size.
๐ฉ๐ฝโ๐ป Solution - Priority Queue
Below is the code for the two pointers approach. ``` class MedianFinder { PriorityQueue pqOne, pqTwo;
public MedianFinder() {
pqOne = new PriorityQueue<>((a,b) -> b - a); pqTwo = new PriorityQueue<>();
}
public void addNum(int num) {
pqOne.add(num);
if(!pqOne.isEmpty() && !pqTwo.isEmpty() &&
pqOne.peek() > pqTwo.peek()
) {
pqTwo.add(pqOne.poll());
}
if(pqOne.size() > pqTwo.size() + 1) {
pqTwo.add(pqOne.poll());
}
if(pqTwo.size() > pqOne.size() + 1) {
pqOne.add(pqTwo.poll());
}
}
public double findMedian() {
int s1 = pqOne.size();
int s2 = pqTwo.size();
if(s1 > s2) {
return (double) pqOne.peek();
}
else if(s2 > s1) {
return (double) pqTwo.peek();
}
double first = pqOne.peek();
double second = pqTwo.peek();
return (first + second) / 2.0;
}
}
Time Complexity:
- findMedian: O(1)
- addNum = O(log n) Space Complexity: O(n) ```
You can find the link to the GitHub repo for this question here: 295. Find Median from Data Stream.
Conclusion
That's a wrap for today's problem. If you liked my explanation then please do drop a like/ comment. Also, please correct me if I've made any mistakes or if you want me to improve something!
Thank you for reading!