Skip to content

Commit 26a453a

Browse files
authored
Merge pull request #1042 from Aditi22Bansal/main
Solved leetcode problem 295- Find median from data stream.md (Hard)
2 parents 6e6741e + 3b87e40 commit 26a453a

File tree

1 file changed

+180
-0
lines changed

1 file changed

+180
-0
lines changed
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
---
2+
id: median-finder
3+
title: Median Finder
4+
sidebar_label: Median Finder
5+
tags:
6+
- Heap
7+
- Data Structure
8+
- C++
9+
- Java
10+
- Python
11+
description: "This document provides a solution to the Median Finder problem, where you need to efficiently find the median of a stream of numbers."
12+
---
13+
14+
## Problem
15+
The MedianFinder class is designed to efficiently find the median of a stream of numbers. You can add numbers to the stream using the `addNum` method and retrieve the median using the `findMedian` method.
16+
17+
## Solution
18+
The approach uses two heaps:
19+
- A max heap to store the smaller half of the numbers
20+
- A min heap to store the larger half of the numbers
21+
22+
The median can be found in constant time by looking at the tops of the heaps.
23+
24+
### Step-by-Step Explanation
25+
26+
1. **Initialize two heaps**:
27+
- `maxHeap` for the lower half of the data (inverted to act like a max heap using negative values).
28+
- `minHeap` for the upper half of the data.
29+
30+
2. **Add number**:
31+
- If the number is less than or equal to the maximum of `maxHeap`, push it to `maxHeap`.
32+
- Otherwise, push it to `minHeap`.
33+
- Balance the heaps if necessary to ensure `maxHeap` always has equal or one more element than `minHeap`.
34+
35+
3. **Find median**:
36+
- If the heaps have equal sizes, the median is the average of the roots of both heaps.
37+
- Otherwise, the median is the root of `maxHeap`.
38+
39+
## Code in Different Languages
40+
41+
<Tabs>
42+
<TabItem value="cpp" label="C++">
43+
<SolutionAuthor name="@User"/>
44+
45+
## C++
46+
```cpp
47+
#include <queue>
48+
#include <vector>
49+
50+
class MedianFinder {
51+
public:
52+
void addNum(int num) {
53+
if (maxHeap.empty() || num <= maxHeap.top())
54+
maxHeap.push(num);
55+
else
56+
minHeap.push(num);
57+
58+
// Balance the two heaps so that
59+
// |maxHeap| >= |minHeap| and |maxHeap| - |minHeap| <= 1.
60+
if (maxHeap.size() < minHeap.size())
61+
maxHeap.push(minHeap.top()), minHeap.pop();
62+
else if (maxHeap.size() - minHeap.size() > 1)
63+
minHeap.push(maxHeap.top()), maxHeap.pop();
64+
}
65+
66+
double findMedian() {
67+
if (maxHeap.size() == minHeap.size())
68+
return (maxHeap.top() + minHeap.top()) / 2.0;
69+
return maxHeap.top();
70+
}
71+
72+
private:
73+
std::priority_queue<int> maxHeap;
74+
std::priority_queue<int, std::vector<int>, std::greater<int>> minHeap;
75+
};
76+
77+
int main() {
78+
MedianFinder mf;
79+
mf.addNum(1);
80+
mf.addNum(2);
81+
std::cout << mf.findMedian() << std::endl; // Output: 1.5
82+
mf.addNum(3);
83+
std::cout << mf.findMedian() << std::endl; // Output: 2
84+
}
85+
```
86+
</TabItem>
87+
<TabItem value="java" label="Java">
88+
<SolutionAuthor name="@User"/>
89+
90+
## Java
91+
```java
92+
import java.util.Collections;
93+
import java.util.PriorityQueue;
94+
import java.util.Queue;
95+
96+
public class MedianFinder {
97+
private Queue<Integer> maxHeap = new PriorityQueue<>(Collections.reverseOrder());
98+
private Queue<Integer> minHeap = new PriorityQueue<>();
99+
100+
public void addNum(int num) {
101+
if (maxHeap.isEmpty() || num <= maxHeap.peek())
102+
maxHeap.offer(num);
103+
else
104+
minHeap.offer(num);
105+
106+
// Balance the two heaps so that
107+
// |maxHeap| >= |minHeap| and |maxHeap| - |minHeap| <= 1.
108+
if (maxHeap.size() < minHeap.size())
109+
maxHeap.offer(minHeap.poll());
110+
else if (maxHeap.size() - minHeap.size() > 1)
111+
minHeap.offer(maxHeap.poll());
112+
}
113+
114+
public double findMedian() {
115+
if (maxHeap.size() == minHeap.size())
116+
return (double) (maxHeap.peek() + minHeap.peek()) / 2.0;
117+
return (double) maxHeap.peek();
118+
}
119+
120+
public static void main(String[] args) {
121+
MedianFinder mf = new MedianFinder();
122+
mf.addNum(1);
123+
mf.addNum(2);
124+
System.out.println(mf.findMedian()); // Output: 1.5
125+
mf.addNum(3);
126+
System.out.println(mf.findMedian()); // Output: 2
127+
}
128+
}
129+
```
130+
131+
</TabItem>
132+
<TabItem value="python" label="Python">
133+
<SolutionAuthor name="@User"/>
134+
135+
## Python
136+
```python
137+
import heapq
138+
139+
class MedianFinder:
140+
def __init__(self):
141+
self.maxHeap = []
142+
self.minHeap = []
143+
144+
def addNum(self, num: int) -> None:
145+
if not self.maxHeap or num <= -self.maxHeap[0]:
146+
heapq.heappush(self.maxHeap, -num)
147+
else:
148+
heapq.heappush(self.minHeap, num)
149+
150+
# Balance the two heaps so that
151+
# |maxHeap| >= |minHeap| and |maxHeap| - |minHeap| <= 1.
152+
if len(self.maxHeap) < len(self.minHeap):
153+
heapq.heappush(self.maxHeap, -heapq.heappop(self.minHeap))
154+
elif len(self.maxHeap) - len(self.minHeap) > 1:
155+
heapq.heappush(self.minHeap, -heapq.heappop(self.maxHeap))
156+
157+
def findMedian(self) -> float:
158+
if len(self.maxHeap) == len(self.minHeap):
159+
return (-self.maxHeap[0] + self.minHeap[0]) / 2.0
160+
return -self.maxHeap[0]
161+
162+
# Example usage
163+
mf = MedianFinder()
164+
mf.addNum(1)
165+
mf.addNum(2)
166+
print(mf.findMedian()) # Output: 1.5
167+
mf.addNum(3)
168+
print(mf.findMedian()) # Output: 2
169+
```
170+
</TabItem>
171+
</Tabs>
172+
173+
# Complexity Analysis
174+
## Time Complexity: $O(log N)$ for addNum, $O(1)$ for findMedian
175+
### Reason:
176+
Adding a number involves heap insertion which takes $O(log N)$ time. Finding the median involves looking at the top elements of the heaps, which takes $O(1)$ time.
177+
178+
## Space Complexity: $O(N)$
179+
### Reason:
180+
We are storing all the numbers in the two heaps.

0 commit comments

Comments
 (0)