|
4 | 4 | import java.util.PriorityQueue; |
5 | 5 |
|
6 | 6 | /** |
7 | | - * @author shrutisheoran |
| 7 | + * A generic abstract class to compute the median of a dynamically growing stream of numbers. |
| 8 | + * |
| 9 | + * @param <T> the number type, must extend Number and be Comparable |
| 10 | + * |
| 11 | + * Usage: |
| 12 | + * Extend this class and implement {@code calculateAverage(T a, T b)} to define how averaging is done. |
8 | 13 | */ |
9 | 14 | public abstract class MedianOfRunningArray<T extends Number & Comparable<T>> { |
10 | 15 |
|
11 | | - private PriorityQueue<T> maxHeap; |
12 | | - private PriorityQueue<T> minHeap; |
| 16 | + private final PriorityQueue<T> maxHeap; // Lower half (max-heap) |
| 17 | + private final PriorityQueue<T> minHeap; // Upper half (min-heap) |
13 | 18 |
|
14 | | - // Constructor |
15 | 19 | public MedianOfRunningArray() { |
16 | | - this.maxHeap = new PriorityQueue<>(Collections.reverseOrder()); // Max Heap |
17 | | - this.minHeap = new PriorityQueue<>(); // Min Heap |
| 20 | + this.maxHeap = new PriorityQueue<>(Collections.reverseOrder()); |
| 21 | + this.minHeap = new PriorityQueue<>(); |
18 | 22 | } |
19 | 23 |
|
20 | | - /* |
21 | | - Inserting lower half of array to max Heap |
22 | | - and upper half to min heap |
| 24 | + /** |
| 25 | + * Inserts a new number into the data structure. |
| 26 | + * |
| 27 | + * @param element the number to insert |
23 | 28 | */ |
24 | | - public void insert(final T e) { |
25 | | - if (!minHeap.isEmpty() && e.compareTo(minHeap.peek()) < 0) { |
26 | | - maxHeap.offer(e); |
27 | | - if (maxHeap.size() > minHeap.size() + 1) { |
28 | | - minHeap.offer(maxHeap.poll()); |
29 | | - } |
| 29 | + public final void insert(final T element) { |
| 30 | + if (!minHeap.isEmpty() && element.compareTo(minHeap.peek()) < 0) { |
| 31 | + maxHeap.offer(element); |
| 32 | + balanceHeapsIfNeeded(); |
30 | 33 | } else { |
31 | | - minHeap.offer(e); |
32 | | - if (minHeap.size() > maxHeap.size() + 1) { |
33 | | - maxHeap.offer(minHeap.poll()); |
34 | | - } |
| 34 | + minHeap.offer(element); |
| 35 | + balanceHeapsIfNeeded(); |
35 | 36 | } |
36 | 37 | } |
37 | 38 |
|
38 | | - /* |
39 | | - Returns median at any given point |
| 39 | + /** |
| 40 | + * Returns the median of the current elements. |
| 41 | + * |
| 42 | + * @return the median value |
| 43 | + * @throws IllegalArgumentException if no elements have been inserted |
40 | 44 | */ |
41 | | - public T median() { |
| 45 | + public final T getMedian() { |
42 | 46 | if (maxHeap.isEmpty() && minHeap.isEmpty()) { |
43 | | - throw new IllegalArgumentException("Enter at least 1 element, Median of empty list is not defined!"); |
44 | | - } else if (maxHeap.size() == minHeap.size()) { |
45 | | - T maxHeapTop = maxHeap.peek(); |
46 | | - T minHeapTop = minHeap.peek(); |
47 | | - return calculateAverage(maxHeapTop, minHeapTop); |
| 47 | + throw new IllegalArgumentException("Median is undefined for an empty data set."); |
48 | 48 | } |
49 | | - return maxHeap.size() > minHeap.size() ? maxHeap.peek() : minHeap.peek(); |
| 49 | + |
| 50 | + if (maxHeap.size() == minHeap.size()) { |
| 51 | + return calculateAverage(maxHeap.peek(), minHeap.peek()); |
| 52 | + } |
| 53 | + |
| 54 | + return (maxHeap.size() > minHeap.size()) ? maxHeap.peek() : minHeap.peek(); |
50 | 55 | } |
51 | 56 |
|
52 | | - public abstract T calculateAverage(T a, T b); |
| 57 | + /** |
| 58 | + * Calculates the average between two values. |
| 59 | + * Concrete subclasses must define how averaging works (e.g., for Integer, Double, etc.). |
| 60 | + * |
| 61 | + * @param a first number |
| 62 | + * @param b second number |
| 63 | + * @return the average of a and b |
| 64 | + */ |
| 65 | + protected abstract T calculateAverage(T a, T b); |
| 66 | + |
| 67 | + /** |
| 68 | + * Balances the two heaps so that their sizes differ by at most 1. |
| 69 | + */ |
| 70 | + private void balanceHeapsIfNeeded() { |
| 71 | + if (maxHeap.size() > minHeap.size() + 1) { |
| 72 | + minHeap.offer(maxHeap.poll()); |
| 73 | + } else if (minHeap.size() > maxHeap.size() + 1) { |
| 74 | + maxHeap.offer(minHeap.poll()); |
| 75 | + } |
| 76 | + } |
53 | 77 | } |
0 commit comments