-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMedianTracker.java
70 lines (60 loc) · 1.88 KB
/
MedianTracker.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package com.cunningdj.grokJava;
import java.util.Comparator;
import java.util.PriorityQueue;
/*
Median Tracker is a practice case for the TWO HEAPS pattern
*/
class MedianTracker {
private PriorityQueue<Integer> topMinHeap;
private PriorityQueue<Integer> bottomMaxHeap;
// MAIN
public static void main(String[] args) {
Tester tester = new Tester();
String testTitle="MEDIAN_TRACKER";
MedianTracker mt = new MedianTracker();
tester.isNull(mt.findMedian(), testTitle);
mt.add(1);
tester.doubleEquals(1, mt.findMedian(), testTitle);
mt.add(3);
tester.doubleEquals(2, mt.findMedian(), testTitle);
mt.add(2);
tester.doubleEquals(2, mt.findMedian(), testTitle);
mt.add(4);
tester.doubleEquals(2.5, mt.findMedian(), testTitle);
}
// CONSTRUCTOR(S)
public MedianTracker() {
this.topMinHeap = new PriorityQueue<>();
this.bottomMaxHeap = new PriorityQueue<>(Comparator.reverseOrder());
}
// PUBLIC
public void add(int num) {
// We will design this such that the bottom max heap will have 0-1 more elements than the top min heap
// (if 1 more, then that is the median)
if (bottomMaxHeap.size() == 0 || num <= bottomMaxHeap.peek()) {
bottomMaxHeap.add(num);
} else {
topMinHeap.add(num);
}
rebalanceHeaps();
}
public Double findMedian() {
if (bottomMaxHeap.size() == 0) {
// Return null if there is no median (both heaps empty)
return null;
} else if (bottomMaxHeap.size() > topMinHeap.size()) {
return bottomMaxHeap.peek() / 1.0;
} else {
// Divide each by 2.0 individually to avoid hitting Integer.MAX_VALUE when adding
return (bottomMaxHeap.peek() / 2.0) + (topMinHeap.peek() / 2.0);
}
}
// PRIVATE
private void rebalanceHeaps() {
if (bottomMaxHeap.size() < topMinHeap.size()) {
bottomMaxHeap.add(topMinHeap.poll());
} else if (bottomMaxHeap.size() > topMinHeap.size() + 1) {
topMinHeap.add(bottomMaxHeap.poll());
}
}
}