4848#include < vector>
4949
5050// Simple (Brute-force) Solution
51- // Stores numbers in a vector and sorts on each insertion.
52- // Complexity: O(n log n) per insertion.
51+ //
52+ // Stores all numbers in a vector and sorts it after each insertion.
53+ //
54+ // Time Complexity:
55+ // - insert(): O(n log n) due to sorting after every insertion.
56+ // - getMedian(): O(1).
57+ //
58+ // Space Complexity:
59+ // - O(n) to store all elements.
60+ //
61+ // This approach is simple but inefficient for large data streams.
5362class SimpleMedianCalculator {
5463public:
5564 void insert (double num) {
@@ -73,8 +82,19 @@ class SimpleMedianCalculator {
7382};
7483
7584// Optimal (Efficient) Solution
76- // Uses two heaps: a max-heap for the lower half and a min-heap for the upper
77- // half. Complexity: O(log n) per insertion, O(1) median retrieval.
85+ //
86+ // Uses two heaps:
87+ // - Max-heap for the lower half of numbers
88+ // - Min-heap for the upper half
89+ //
90+ // Time Complexity:
91+ // - insert(): O(log n) due to heap insertion and rebalancing.
92+ // - getMedian(): O(1).
93+ //
94+ // Space Complexity:
95+ // - O(n) to store all elements across both heaps.
96+ //
97+ // This is the optimal solution for maintaining the median of a data stream.
7898class OptimalMedianCalculator {
7999public:
80100 void insert (double num) {
@@ -84,7 +104,7 @@ class OptimalMedianCalculator {
84104 maxHeap.push (num);
85105 }
86106
87- // Balance the heaps to ensure the size difference is not more than 1.
107+ // Balance the heaps so their sizes differ by at most 1.
88108 if (minHeap.size () > maxHeap.size () + 1 ) {
89109 maxHeap.push (minHeap.top ());
90110 minHeap.pop ();
@@ -107,12 +127,24 @@ class OptimalMedianCalculator {
107127private:
108128 std::priority_queue<double , std::vector<double >, std::greater<double >>
109129 minHeap;
110- std::priority_queue<double > maxHeap; // Default is max-heap.
130+ std::priority_queue<double > maxHeap;
111131};
112132
133+
113134// Alternative (Educational) Solution
114- // Uses a multiset to maintain sorted order with logarithmic insertions
115- // and an iterator to track the median position.
135+ //
136+ // Uses a multiset to maintain sorted order and an iterator pointing
137+ // to the current median.
138+ //
139+ // Time Complexity:
140+ // - insert(): O(log n) due to multiset insertion.
141+ // - getMedian(): O(1).
142+ //
143+ // Space Complexity:
144+ // - O(n) to store all elements.
145+ //
146+ // This solution is elegant and easy to reason about, but typically
147+ // slower in practice than the heap-based approach due to tree overhead.
116148class AlternativeMedianCalculator {
117149public:
118150 void insert (double num) {
@@ -123,11 +155,11 @@ class AlternativeMedianCalculator {
123155 data.insert (num);
124156 // Adjust the median iterator based on the inserted value.
125157 if (num < *medianIt) {
126- if (data.size () % 2 == 0 ) { // even -> odd: move iterator left.
158+ if (data.size () % 2 == 0 ) { // even -> odd
127159 --medianIt;
128160 }
129161 } else {
130- if (data.size () % 2 == 1 ) { // odd -> even: move iterator right.
162+ if (data.size () % 2 == 1 ) { // odd -> even
131163 ++medianIt;
132164 }
133165 }
0 commit comments