Skip to content

Commit 7f77ebd

Browse files
committed
Add solution 295
1 parent 51f5118 commit 7f77ebd

File tree

3 files changed

+123
-0
lines changed

3 files changed

+123
-0
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ Complete solutions to Leetcode problems, updated daily.
7070
| 032 | [Longest Valid Parentheses](https://github.com/doocs/leetcode/tree/master/solution/032.Longest%20Valid%20Parentheses) | `String`, `Dynamic Programming` |
7171
| 084 | [Largest Rectangle in Histogram](https://github.com/doocs/leetcode/tree/master/solution/084.Largest%20Rectangle%20in%20Histogram) | `Array`, `Stack` |
7272
| 145 | [Binary Tree Postorder Traversal](https://github.com/doocs/leetcode/tree/master/solution/145.Binary%20Tree%20Postorder%20Traversal) | `Stack`, `Tree` |
73+
| 295 | [Find Median from Data Stream](https://github.com/doocs/leetcode/tree/master/solution/295.Find%20Median%20from%20Data%20Stream) | `Heap`, `Design` |
7374

7475
## Contributions
7576
I'm looking for long-term contributors/partners to this repo! Send me PRs if you're interested! See the following:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
## 数据流的中位数
2+
### 题目描述
3+
4+
中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。
5+
6+
例如,
7+
8+
[2,3,4] 的中位数是 3
9+
10+
[2,3] 的中位数是 (2 + 3) / 2 = 2.5
11+
12+
设计一个支持以下两种操作的数据结构:
13+
14+
- void addNum(int num) - 从数据流中添加一个整数到数据结构中。
15+
- double findMedian() - 返回目前所有元素的中位数。
16+
17+
示例:
18+
```
19+
addNum(1)
20+
addNum(2)
21+
findMedian() -> 1.5
22+
addNum(3)
23+
findMedian() -> 2
24+
```
25+
26+
进阶:
27+
28+
- 1. 如果数据流中所有整数都在 0 到 100 范围内,你将如何优化你的算法?
29+
- 2. 如果数据流中 99% 的整数都在 0 到 100 范围内,你将如何优化你的算法?
30+
31+
### 解法
32+
维护一个大根堆 bigRoot 和一个小根堆 smallRoot,若有 n 个数,较小的 n/2 个数放在大根堆,而较大的 n/2 个数放在小根堆。
33+
34+
- 若其中一个堆的元素个数比另一个堆的元素个数大 1,弹出堆顶元素到另一个堆。
35+
- 获取中位数时,若两个堆的元素个数相等,返回两个堆堆顶的平均值。否则返回元素个数较多的堆的堆顶。
36+
37+
```java
38+
class MedianFinder {
39+
40+
private PriorityQueue<Integer> bigRoot;
41+
private PriorityQueue<Integer> smallRoot;
42+
43+
/** initialize your data structure here. */
44+
public MedianFinder() {
45+
bigRoot = new PriorityQueue<>(Comparator.reverseOrder());
46+
smallRoot = new PriorityQueue<>(Integer::compareTo);
47+
}
48+
49+
public void addNum(int num) {
50+
if (bigRoot.isEmpty() || bigRoot.peek() > num) {
51+
bigRoot.add(num);
52+
} else {
53+
smallRoot.add(num);
54+
}
55+
56+
int size1 = bigRoot.size();
57+
int size2 = smallRoot.size();
58+
if (size1 - size2 > 1) {
59+
smallRoot.add(bigRoot.poll());
60+
} else if (size2 - size1 > 1) {
61+
bigRoot.add(smallRoot.poll());
62+
}
63+
}
64+
65+
public double findMedian() {
66+
int size1 = bigRoot.size();
67+
int size2 = smallRoot.size();
68+
69+
return size1 == size2
70+
? (bigRoot.peek() + smallRoot.peek()) * 1.0 / 2
71+
: (size1 > size2 ? bigRoot.peek() : smallRoot.peek());
72+
}
73+
}
74+
75+
/**
76+
* Your MedianFinder object will be instantiated and called as such:
77+
* MedianFinder obj = new MedianFinder();
78+
* obj.addNum(num);
79+
* double param_2 = obj.findMedian();
80+
*/
81+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
class MedianFinder {
2+
3+
private PriorityQueue<Integer> bigRoot;
4+
private PriorityQueue<Integer> smallRoot;
5+
6+
/** initialize your data structure here. */
7+
public MedianFinder() {
8+
bigRoot = new PriorityQueue<>(Comparator.reverseOrder());
9+
smallRoot = new PriorityQueue<>(Integer::compareTo);
10+
}
11+
12+
public void addNum(int num) {
13+
if (bigRoot.isEmpty() || bigRoot.peek() > num) {
14+
bigRoot.add(num);
15+
} else {
16+
smallRoot.add(num);
17+
}
18+
19+
int size1 = bigRoot.size();
20+
int size2 = smallRoot.size();
21+
if (size1 - size2 > 1) {
22+
smallRoot.add(bigRoot.poll());
23+
} else if (size2 - size1 > 1) {
24+
bigRoot.add(smallRoot.poll());
25+
}
26+
}
27+
28+
public double findMedian() {
29+
int size1 = bigRoot.size();
30+
int size2 = smallRoot.size();
31+
32+
return size1 == size2 ? (bigRoot.peek() + smallRoot.peek()) * 1.0 / 2
33+
: (size1 > size2 ? bigRoot.peek() : smallRoot.peek());
34+
}
35+
}
36+
37+
/**
38+
* Your MedianFinder object will be instantiated and called as such:
39+
* MedianFinder obj = new MedianFinder(); obj.addNum(num); double param_2 =
40+
* obj.findMedian();
41+
*/

0 commit comments

Comments
 (0)