Skip to content

Commit 92af611

Browse files
rain84yanglbme
andauthored
feat: add solutions to lc problem: No.0295 (doocs#3166)
Co-authored-by: Libin YANG <contact@yanglibin.info>
1 parent 43a0d90 commit 92af611

File tree

11 files changed

+657
-452
lines changed

11 files changed

+657
-452
lines changed

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

Lines changed: 220 additions & 154 deletions
Large diffs are not rendered by default.

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

Lines changed: 224 additions & 148 deletions
Large diffs are not rendered by default.
Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,31 @@
11
class MedianFinder {
22
public:
3-
/** initialize your data structure here. */
43
MedianFinder() {
54
}
65

76
void addNum(int num) {
8-
q1.push(num);
9-
q2.push(q1.top());
10-
q1.pop();
11-
if (q2.size() - q1.size() > 1) {
12-
q1.push(q2.top());
13-
q2.pop();
7+
maxQ.push(num);
8+
minQ.push(maxQ.top());
9+
maxQ.pop();
10+
11+
if (minQ.size() > maxQ.size() + 1) {
12+
maxQ.push(minQ.top());
13+
minQ.pop();
1414
}
1515
}
1616

1717
double findMedian() {
18-
if (q2.size() > q1.size()) {
19-
return q2.top();
20-
}
21-
return (double) (q1.top() + q2.top()) / 2;
18+
return minQ.size() == maxQ.size() ? (minQ.top() + maxQ.top()) / 2.0 : minQ.top();
2219
}
2320

2421
private:
25-
priority_queue<int, vector<int>, greater<int>> q1;
26-
priority_queue<int> q2;
22+
priority_queue<int> maxQ;
23+
priority_queue<int, vector<int>, greater<int>> minQ;
2724
};
2825

2926
/**
3027
* Your MedianFinder object will be instantiated and called as such:
3128
* MedianFinder* obj = new MedianFinder();
3229
* obj->addNum(num);
3330
* double param_2 = obj->findMedian();
34-
*/
31+
*/

solution/0200-0299/0295.Find Median from Data Stream/Solution.cs

Lines changed: 7 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,21 @@
11
public class MedianFinder {
2-
private List<int> nums;
3-
private int curIndex;
2+
private PriorityQueue<int, int> minQ = new PriorityQueue<int, int>();
3+
private PriorityQueue<int, int> maxQ = new PriorityQueue<int, int>(Comparer<int>.Create((a, b) => b.CompareTo(a)));
44

5-
/** initialize your data structure here. */
65
public MedianFinder() {
7-
nums = new List<int>();
8-
}
96

10-
private int FindIndex(int val) {
11-
int left = 0;
12-
int right = nums.Count - 1;
13-
while (left <= right) {
14-
int mid = left + (right - left) / 2;
15-
if (val > nums[mid]) {
16-
left = mid + 1;
17-
} else {
18-
right = mid - 1;
19-
}
20-
}
21-
return left;
227
}
238

249
public void AddNum(int num) {
25-
if (nums.Count == 0) {
26-
nums.Add(num);
27-
curIndex = 0;
28-
} else {
29-
curIndex = FindIndex(num);
30-
if (curIndex == nums.Count) {
31-
nums.Add(num);
32-
} else {
33-
nums.Insert(curIndex, num);
34-
}
10+
maxQ.Enqueue(num, num);
11+
minQ.Enqueue(maxQ.Peek(), maxQ.Dequeue());
12+
if (minQ.Count > maxQ.Count + 1) {
13+
maxQ.Enqueue(minQ.Peek(), minQ.Dequeue());
3514
}
3615
}
3716

3817
public double FindMedian() {
39-
if (nums.Count % 2 == 1) {
40-
return (double)nums[nums.Count / 2];
41-
} else {
42-
if (nums.Count == 0) {
43-
return 0;
44-
} else {
45-
return (double) (nums[nums.Count / 2 - 1] + nums[nums.Count / 2]) / 2;
46-
}
47-
}
18+
return minQ.Count == maxQ.Count ? (minQ.Peek() + maxQ.Peek()) / 2.0 : minQ.Peek();
4819
}
4920
}
5021

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,29 @@
11
type MedianFinder struct {
2-
q1 hp
3-
q2 hp
2+
minq hp
3+
maxq hp
44
}
55

6-
/** initialize your data structure here. */
76
func Constructor() MedianFinder {
87
return MedianFinder{hp{}, hp{}}
98
}
109

1110
func (this *MedianFinder) AddNum(num int) {
12-
heap.Push(&this.q1, num)
13-
heap.Push(&this.q2, -heap.Pop(&this.q1).(int))
14-
if this.q2.Len()-this.q1.Len() > 1 {
15-
heap.Push(&this.q1, -heap.Pop(&this.q2).(int))
11+
minq, maxq := &this.minq, &this.maxq
12+
heap.Push(maxq, -num)
13+
heap.Push(minq, -heap.Pop(maxq).(int))
14+
if minq.Len()-maxq.Len() > 1 {
15+
heap.Push(maxq, -heap.Pop(minq).(int))
1616
}
1717
}
1818

1919
func (this *MedianFinder) FindMedian() float64 {
20-
if this.q2.Len() > this.q1.Len() {
21-
return -float64(this.q2.IntSlice[0])
20+
minq, maxq := this.minq, this.maxq
21+
if minq.Len() == maxq.Len() {
22+
return float64(minq.IntSlice[0]-maxq.IntSlice[0]) / 2
2223
}
23-
return float64(this.q1.IntSlice[0]-this.q2.IntSlice[0]) / 2.0
24+
return float64(minq.IntSlice[0])
2425
}
2526

26-
/**
27-
* Your MedianFinder object will be instantiated and called as such:
28-
* obj := Constructor();
29-
* obj.AddNum(num);
30-
* param_2 := obj.FindMedian();
31-
*/
32-
3327
type hp struct{ sort.IntSlice }
3428

3529
func (h hp) Less(i, j int) bool { return h.IntSlice[i] < h.IntSlice[j] }
@@ -39,4 +33,11 @@ func (h *hp) Pop() any {
3933
v := a[len(a)-1]
4034
h.IntSlice = a[:len(a)-1]
4135
return v
42-
}
36+
}
37+
38+
/**
39+
* Your MedianFinder object will be instantiated and called as such:
40+
* obj := Constructor();
41+
* obj.AddNum(num);
42+
* param_2 := obj.FindMedian();
43+
*/
Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,20 @@
11
class MedianFinder {
2-
private PriorityQueue<Integer> q1 = new PriorityQueue<>();
3-
private PriorityQueue<Integer> q2 = new PriorityQueue<>(Collections.reverseOrder());
2+
private PriorityQueue<Integer> minQ = new PriorityQueue<>();
3+
private PriorityQueue<Integer> maxQ = new PriorityQueue<>(Collections.reverseOrder());
44

5-
/** initialize your data structure here. */
65
public MedianFinder() {
76
}
87

98
public void addNum(int num) {
10-
q1.offer(num);
11-
q2.offer(q1.poll());
12-
if (q2.size() - q1.size() > 1) {
13-
q1.offer(q2.poll());
9+
maxQ.offer(num);
10+
minQ.offer(maxQ.poll());
11+
if (minQ.size() - maxQ.size() > 1) {
12+
maxQ.offer(minQ.poll());
1413
}
1514
}
1615

1716
public double findMedian() {
18-
if (q2.size() > q1.size()) {
19-
return q2.peek();
20-
}
21-
return (q1.peek() + q2.peek()) * 1.0 / 2;
17+
return minQ.size() == maxQ.size() ? (minQ.peek() + maxQ.peek()) / 2.0 : minQ.peek();
2218
}
2319
}
2420

@@ -27,4 +23,4 @@ public double findMedian() {
2723
* MedianFinder obj = new MedianFinder();
2824
* obj.addNum(num);
2925
* double param_2 = obj.findMedian();
30-
*/
26+
*/
Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,33 @@
1-
/**
2-
* initialize your data structure here.
3-
*/
41
var MedianFinder = function () {
5-
this.val = [];
2+
this.minQ = new MinPriorityQueue();
3+
this.maxQ = new MaxPriorityQueue();
64
};
75

86
/**
97
* @param {number} num
108
* @return {void}
119
*/
1210
MedianFinder.prototype.addNum = function (num) {
13-
let left = 0;
14-
let right = this.val.length;
15-
while (left < right) {
16-
let mid = left + ~~((right - left) / 2);
17-
if (num > this.val[mid]) {
18-
left = mid + 1;
19-
} else {
20-
right = mid;
21-
}
11+
this.maxQ.enqueue(num);
12+
this.minQ.enqueue(this.maxQ.dequeue().element);
13+
if (this.minQ.size() - this.maxQ.size() > 1) {
14+
this.maxQ.enqueue(this.minQ.dequeue().element);
2215
}
23-
this.val.splice(left, 0, num);
2416
};
2517

2618
/**
2719
* @return {number}
2820
*/
2921
MedianFinder.prototype.findMedian = function () {
30-
let mid = ~~(this.val.length / 2);
31-
return this.val.length % 2 ? this.val[mid] : (this.val[mid - 1] + this.val[mid]) / 2;
22+
if (this.minQ.size() === this.maxQ.size()) {
23+
return (this.minQ.front().element + this.maxQ.front().element) / 2;
24+
}
25+
return this.minQ.front().element;
3226
};
27+
28+
/**
29+
* Your MedianFinder object will be instantiated and called as such:
30+
* var obj = new MedianFinder()
31+
* obj.addNum(num)
32+
* var param_2 = obj.findMedian()
33+
*/

solution/0200-0299/0295.Find Median from Data Stream/Solution.py

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,18 @@
11
class MedianFinder:
2+
23
def __init__(self):
3-
"""
4-
initialize your data structure here.
5-
"""
6-
self.h1 = []
7-
self.h2 = []
4+
self.minq = []
5+
self.maxq = []
86

97
def addNum(self, num: int) -> None:
10-
heappush(self.h1, num)
11-
heappush(self.h2, -heappop(self.h1))
12-
if len(self.h2) - len(self.h1) > 1:
13-
heappush(self.h1, -heappop(self.h2))
8+
heappush(self.minq, -heappushpop(self.maxq, -num))
9+
if len(self.minq) - len(self.maxq) > 1:
10+
heappush(self.maxq, -heappop(self.minq))
1411

1512
def findMedian(self) -> float:
16-
if len(self.h2) > len(self.h1):
17-
return -self.h2[0]
18-
return (self.h1[0] - self.h2[0]) / 2
13+
if len(self.minq) == len(self.maxq):
14+
return (self.minq[0] - self.maxq[0]) / 2
15+
return self.minq[0]
1916

2017

2118
# Your MedianFinder object will be instantiated and called as such:
Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,35 @@
1+
use std::cmp::Reverse;
2+
use std::collections::BinaryHeap;
3+
14
struct MedianFinder {
2-
nums: Vec<i32>,
5+
minQ: BinaryHeap<Reverse<i32>>,
6+
maxQ: BinaryHeap<i32>,
37
}
48

5-
/**
6-
* `&self` means the method takes an immutable reference.
7-
* If you need a mutable reference, change it to `&mut self` instead.
8-
*/
99
impl MedianFinder {
10-
/** initialize your data structure here. */
1110
fn new() -> Self {
12-
Self { nums: Vec::new() }
11+
MedianFinder {
12+
minQ: BinaryHeap::new(),
13+
maxQ: BinaryHeap::new(),
14+
}
1315
}
1416

1517
fn add_num(&mut self, num: i32) {
16-
let mut l = 0;
17-
let mut r = self.nums.len();
18-
while l < r {
19-
let mid = (l + r) >> 1;
20-
if self.nums[mid] < num {
21-
l = mid + 1;
22-
} else {
23-
r = mid;
24-
}
18+
self.maxQ.push(num);
19+
self.minQ.push(Reverse(self.maxQ.pop().unwrap()));
20+
21+
if self.minQ.len() > self.maxQ.len() + 1 {
22+
self.maxQ.push(self.minQ.pop().unwrap().0);
2523
}
26-
self.nums.insert(l, num);
2724
}
2825

2926
fn find_median(&self) -> f64 {
30-
let n = self.nums.len();
31-
if (n & 1) == 1 {
32-
return f64::from(self.nums[n >> 1]);
27+
if self.minQ.len() == self.maxQ.len() {
28+
let min_top = self.minQ.peek().unwrap().0;
29+
let max_top = *self.maxQ.peek().unwrap();
30+
(min_top + max_top) as f64 / 2.0
31+
} else {
32+
self.minQ.peek().unwrap().0 as f64
3333
}
34-
f64::from(self.nums[n >> 1] + self.nums[(n >> 1) - 1]) / 2.0
3534
}
3635
}

0 commit comments

Comments
 (0)