Skip to content

Commit 3dc3258

Browse files
committed
feat: add solutions to lc/lcci problems: Find Median from Data Stream
* leetcode problem: No.0295. Find Median from Data Stream * lcci problem: No.17.20. Continuous Median
1 parent 066dcad commit 3dc3258

File tree

8 files changed

+191
-83
lines changed

8 files changed

+191
-83
lines changed

lcci/17.20.Continuous Median/README.md

+20-18
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ findMedian() -> 2
3636
<!-- 这里可写通用的实现逻辑 -->
3737

3838
- 创建大根堆、小根堆,其中:大根堆存放较小的一半元素,小根堆存放较大的一半元素。
39-
- 添加元素时,若两堆元素个数相等,放入小根堆(使得小根堆个数多 1);若不等,放入大根堆(使得大小根堆元素个数相等)
40-
- 取中位数时,若两堆元素个数相等,取两堆顶求平均值;若不等,取小根堆堆顶
39+
- 添加元素时,先放入小根堆,然后将小根堆对顶元素弹出并放入大根堆(使得大根堆个数多 1);若大小根堆元素个数差超过 1,则将大根堆元素弹出放入小根堆。
40+
- 取中位数时,若大根堆元素较多,取大根堆堆顶,否则取两堆顶元素和的平均值
4141

4242
<!-- tabs:start -->
4343

@@ -52,18 +52,19 @@ class MedianFinder:
5252
"""
5353
initialize your data structure here.
5454
"""
55-
self.max_heap = []
5655
self.min_heap = []
57-
56+
self.max_heap = []
5857

5958
def addNum(self, num: int) -> None:
60-
if len(self.max_heap) == len(self.min_heap):
61-
heapq.heappush(self.min_heap, -heapq.heappushpop(self.max_heap, -num))
62-
else:
63-
heapq.heappush(self.max_heap, -heapq.heappushpop(self.min_heap, num))
59+
heapq.heappush(self.min_heap, num)
60+
heapq.heappush(self.max_heap, -heapq.heappop(self.min_heap))
61+
if len(self.max_heap) - len(self.min_heap) > 1:
62+
heapq.heappush(self.min_heap, -heapq.heappop(self.max_heap))
6463

6564
def findMedian(self) -> float:
66-
return (-self.max_heap[0] + self.min_heap[0]) / 2 if len(self.max_heap) == len(self.min_heap) else self.min_heap[0]
65+
if len(self.max_heap) > len(self.min_heap):
66+
return -self.max_heap[0]
67+
return (self.min_heap[0] - self.max_heap[0]) / 2
6768

6869

6970
# Your MedianFinder object will be instantiated and called as such:
@@ -78,27 +79,28 @@ class MedianFinder:
7879

7980
```java
8081
class MedianFinder {
81-
private Queue<Integer> minHeap;
82-
private Queue<Integer> maxHeap;
82+
private PriorityQueue<Integer> minHeap;
83+
private PriorityQueue<Integer> maxHeap;
8384

8485
/** initialize your data structure here. */
8586
public MedianFinder() {
8687
minHeap = new PriorityQueue<>();
87-
maxHeap = new PriorityQueue<>((a, b) -> b - a);
88+
maxHeap = new PriorityQueue<>(Collections.reverseOrder());
8889
}
8990

9091
public void addNum(int num) {
91-
if (minHeap.size() == maxHeap.size()) {
92-
maxHeap.offer(num);
92+
minHeap.offer(num);
93+
maxHeap.offer(minHeap.poll());
94+
if (maxHeap.size() - minHeap.size() > 1) {
9395
minHeap.offer(maxHeap.poll());
94-
} else {
95-
minHeap.offer(num);
96-
maxHeap.offer(minHeap.poll());
9796
}
9897
}
9998

10099
public double findMedian() {
101-
return minHeap.size() == maxHeap.size() ? (minHeap.peek() + maxHeap.peek()) / 2.0 : minHeap.peek();
100+
if (maxHeap.size() > minHeap.size()) {
101+
return maxHeap.peek();
102+
}
103+
return (minHeap.peek() + maxHeap.peek()) * 1.0 / 2;
102104
}
103105
}
104106

lcci/17.20.Continuous Median/README_EN.md

+18-16
Original file line numberDiff line numberDiff line change
@@ -50,18 +50,19 @@ class MedianFinder:
5050
"""
5151
initialize your data structure here.
5252
"""
53-
self.max_heap = []
5453
self.min_heap = []
55-
54+
self.max_heap = []
5655

5756
def addNum(self, num: int) -> None:
58-
if len(self.max_heap) == len(self.min_heap):
59-
heapq.heappush(self.min_heap, -heapq.heappushpop(self.max_heap, -num))
60-
else:
61-
heapq.heappush(self.max_heap, -heapq.heappushpop(self.min_heap, num))
57+
heapq.heappush(self.min_heap, num)
58+
heapq.heappush(self.max_heap, -heapq.heappop(self.min_heap))
59+
if len(self.max_heap) - len(self.min_heap) > 1:
60+
heapq.heappush(self.min_heap, -heapq.heappop(self.max_heap))
6261

6362
def findMedian(self) -> float:
64-
return (-self.max_heap[0] + self.min_heap[0]) / 2 if len(self.max_heap) == len(self.min_heap) else self.min_heap[0]
63+
if len(self.max_heap) > len(self.min_heap):
64+
return -self.max_heap[0]
65+
return (self.min_heap[0] - self.max_heap[0]) / 2
6566

6667

6768
# Your MedianFinder object will be instantiated and called as such:
@@ -74,27 +75,28 @@ class MedianFinder:
7475

7576
```java
7677
class MedianFinder {
77-
private Queue<Integer> minHeap;
78-
private Queue<Integer> maxHeap;
78+
private PriorityQueue<Integer> minHeap;
79+
private PriorityQueue<Integer> maxHeap;
7980

8081
/** initialize your data structure here. */
8182
public MedianFinder() {
8283
minHeap = new PriorityQueue<>();
83-
maxHeap = new PriorityQueue<>((a, b) -> b - a);
84+
maxHeap = new PriorityQueue<>(Collections.reverseOrder());
8485
}
8586

8687
public void addNum(int num) {
87-
if (minHeap.size() == maxHeap.size()) {
88-
maxHeap.offer(num);
88+
minHeap.offer(num);
89+
maxHeap.offer(minHeap.poll());
90+
if (maxHeap.size() - minHeap.size() > 1) {
8991
minHeap.offer(maxHeap.poll());
90-
} else {
91-
minHeap.offer(num);
92-
maxHeap.offer(minHeap.poll());
9392
}
9493
}
9594

9695
public double findMedian() {
97-
return minHeap.size() == maxHeap.size() ? (minHeap.peek() + maxHeap.peek()) / 2.0 : minHeap.peek();
96+
if (maxHeap.size() > minHeap.size()) {
97+
return maxHeap.peek();
98+
}
99+
return (minHeap.peek() + maxHeap.peek()) * 1.0 / 2;
98100
}
99101
}
100102

lcci/17.20.Continuous Median/Solution.java

+10-9
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,26 @@
11
class MedianFinder {
2-
private Queue<Integer> minHeap;
3-
private Queue<Integer> maxHeap;
2+
private PriorityQueue<Integer> minHeap;
3+
private PriorityQueue<Integer> maxHeap;
44

55
/** initialize your data structure here. */
66
public MedianFinder() {
77
minHeap = new PriorityQueue<>();
8-
maxHeap = new PriorityQueue<>((a, b) -> b - a);
8+
maxHeap = new PriorityQueue<>(Collections.reverseOrder());
99
}
1010

1111
public void addNum(int num) {
12-
if (minHeap.size() == maxHeap.size()) {
13-
maxHeap.offer(num);
12+
minHeap.offer(num);
13+
maxHeap.offer(minHeap.poll());
14+
if (maxHeap.size() - minHeap.size() > 1) {
1415
minHeap.offer(maxHeap.poll());
15-
} else {
16-
minHeap.offer(num);
17-
maxHeap.offer(minHeap.poll());
1816
}
1917
}
2018

2119
public double findMedian() {
22-
return minHeap.size() == maxHeap.size() ? (minHeap.peek() + maxHeap.peek()) / 2.0 : minHeap.peek();
20+
if (maxHeap.size() > minHeap.size()) {
21+
return maxHeap.peek();
22+
}
23+
return (minHeap.peek() + maxHeap.peek()) * 1.0 / 2;
2324
}
2425
}
2526

lcci/17.20.Continuous Median/Solution.py

+9-8
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,22 @@ def __init__(self):
44
"""
55
initialize your data structure here.
66
"""
7-
self.max_heap = []
87
self.min_heap = []
9-
8+
self.max_heap = []
109

1110
def addNum(self, num: int) -> None:
12-
if len(self.max_heap) == len(self.min_heap):
13-
heapq.heappush(self.min_heap, -heapq.heappushpop(self.max_heap, -num))
14-
else:
15-
heapq.heappush(self.max_heap, -heapq.heappushpop(self.min_heap, num))
11+
heapq.heappush(self.min_heap, num)
12+
heapq.heappush(self.max_heap, -heapq.heappop(self.min_heap))
13+
if len(self.max_heap) - len(self.min_heap) > 1:
14+
heapq.heappush(self.min_heap, -heapq.heappop(self.max_heap))
1615

1716
def findMedian(self) -> float:
18-
return (-self.max_heap[0] + self.min_heap[0]) / 2 if len(self.max_heap) == len(self.min_heap) else self.min_heap[0]
17+
if len(self.max_heap) > len(self.min_heap):
18+
return -self.max_heap[0]
19+
return (self.min_heap[0] - self.max_heap[0]) / 2
1920

2021

2122
# Your MedianFinder object will be instantiated and called as such:
2223
# obj = MedianFinder()
2324
# obj.addNum(num)
24-
# param_2 = obj.findMedian()
25+
# param_2 = obj.findMedian()

solution/0200-0299/0295.Find Median from Data Stream/README.md

+61-3
Original file line numberDiff line numberDiff line change
@@ -36,27 +36,85 @@ findMedian() -&gt; 2</pre>
3636
<li>如果数据流中 99% 的整数都在 0 到 100 范围内,你将如何优化你的算法?</li>
3737
</ol>
3838

39-
4039
## 解法
4140

4241
<!-- 这里可写通用的实现逻辑 -->
4342

43+
- 创建大根堆、小根堆,其中:大根堆存放较小的一半元素,小根堆存放较大的一半元素。
44+
- 添加元素时,先放入小根堆,然后将小根堆对顶元素弹出并放入大根堆(使得大根堆个数多 1);若大小根堆元素个数差超过 1,则将大根堆元素弹出放入小根堆。
45+
- 取中位数时,若大根堆元素较多,取大根堆堆顶,否则取两堆顶元素和的平均值。
46+
4447
<!-- tabs:start -->
4548

4649
### **Python3**
4750

4851
<!-- 这里可写当前语言的特殊实现逻辑 -->
4952

5053
```python
51-
54+
class MedianFinder:
55+
56+
def __init__(self):
57+
"""
58+
initialize your data structure here.
59+
"""
60+
self.min_heap = []
61+
self.max_heap = []
62+
63+
def addNum(self, num: int) -> None:
64+
heapq.heappush(self.min_heap, num)
65+
heapq.heappush(self.max_heap, -heapq.heappop(self.min_heap))
66+
if len(self.max_heap) - len(self.min_heap) > 1:
67+
heapq.heappush(self.min_heap, -heapq.heappop(self.max_heap))
68+
69+
def findMedian(self) -> float:
70+
if len(self.max_heap) > len(self.min_heap):
71+
return -self.max_heap[0]
72+
return (self.min_heap[0] - self.max_heap[0]) / 2
73+
74+
75+
# Your MedianFinder object will be instantiated and called as such:
76+
# obj = MedianFinder()
77+
# obj.addNum(num)
78+
# param_2 = obj.findMedian()
5279
```
5380

5481
### **Java**
5582

5683
<!-- 这里可写当前语言的特殊实现逻辑 -->
5784

5885
```java
59-
86+
class MedianFinder {
87+
private PriorityQueue<Integer> minHeap;
88+
private PriorityQueue<Integer> maxHeap;
89+
90+
/** initialize your data structure here. */
91+
public MedianFinder() {
92+
minHeap = new PriorityQueue<>();
93+
maxHeap = new PriorityQueue<>(Collections.reverseOrder());
94+
}
95+
96+
public void addNum(int num) {
97+
minHeap.offer(num);
98+
maxHeap.offer(minHeap.poll());
99+
if (maxHeap.size() - minHeap.size() > 1) {
100+
minHeap.offer(maxHeap.poll());
101+
}
102+
}
103+
104+
public double findMedian() {
105+
if (maxHeap.size() > minHeap.size()) {
106+
return maxHeap.peek();
107+
}
108+
return (minHeap.peek() + maxHeap.peek()) * 1.0 / 2;
109+
}
110+
}
111+
112+
/**
113+
* Your MedianFinder object will be instantiated and called as such:
114+
* MedianFinder obj = new MedianFinder();
115+
* obj.addNum(num);
116+
* double param_2 = obj.findMedian();
117+
*/
60118
```
61119

62120
### **...**

solution/0200-0299/0295.Find Median from Data Stream/README_EN.md

+57-3
Original file line numberDiff line numberDiff line change
@@ -55,21 +55,75 @@ medianFinder.findMedian(); // return 2.0
5555
<li>If <code>99%</code> of all integer numbers from the stream are in the range <code>[0, 100]</code>, how would you optimize your solution?</li>
5656
</ul>
5757

58-
5958
## Solutions
6059

6160
<!-- tabs:start -->
6261

6362
### **Python3**
6463

6564
```python
66-
65+
class MedianFinder:
66+
67+
def __init__(self):
68+
"""
69+
initialize your data structure here.
70+
"""
71+
self.min_heap = []
72+
self.max_heap = []
73+
74+
def addNum(self, num: int) -> None:
75+
heapq.heappush(self.min_heap, num)
76+
heapq.heappush(self.max_heap, -heapq.heappop(self.min_heap))
77+
if len(self.max_heap) - len(self.min_heap) > 1:
78+
heapq.heappush(self.min_heap, -heapq.heappop(self.max_heap))
79+
80+
def findMedian(self) -> float:
81+
if len(self.max_heap) > len(self.min_heap):
82+
return -self.max_heap[0]
83+
return (self.min_heap[0] - self.max_heap[0]) / 2
84+
85+
86+
# Your MedianFinder object will be instantiated and called as such:
87+
# obj = MedianFinder()
88+
# obj.addNum(num)
89+
# param_2 = obj.findMedian()
6790
```
6891

6992
### **Java**
7093

7194
```java
72-
95+
class MedianFinder {
96+
private PriorityQueue<Integer> minHeap;
97+
private PriorityQueue<Integer> maxHeap;
98+
99+
/** initialize your data structure here. */
100+
public MedianFinder() {
101+
minHeap = new PriorityQueue<>();
102+
maxHeap = new PriorityQueue<>(Collections.reverseOrder());
103+
}
104+
105+
public void addNum(int num) {
106+
minHeap.offer(num);
107+
maxHeap.offer(minHeap.poll());
108+
if (maxHeap.size() - minHeap.size() > 1) {
109+
minHeap.offer(maxHeap.poll());
110+
}
111+
}
112+
113+
public double findMedian() {
114+
if (maxHeap.size() > minHeap.size()) {
115+
return maxHeap.peek();
116+
}
117+
return (minHeap.peek() + maxHeap.peek()) * 1.0 / 2;
118+
}
119+
}
120+
121+
/**
122+
* Your MedianFinder object will be instantiated and called as such:
123+
* MedianFinder obj = new MedianFinder();
124+
* obj.addNum(num);
125+
* double param_2 = obj.findMedian();
126+
*/
73127
```
74128

75129
### **...**

0 commit comments

Comments
 (0)