Let's simulate the solution to the problem using a linear array. At each step, we'll store the incoming numbers in sorted order. We find the insertion position for a new element using binary search. However, the insertion operation itself (for example, if the array is implemented using a data structure) takes linear time. Thus, the overall solution with time complexity O(n^2) will not fit within the time limit.
Declare two heaps: one for maintaining the minimum (a -heap), and another for maintaining the maximum (a -heap). We'll organize their operation so that the following conditions hold:
every element in the -heap is less than every element in the -heap (smaller values are stored in the -heap, and larger values in the -heap);
the sizes of the heaps are equal. If the total number of elements is odd, the -heap should contain one more element than the -heap.
When adding a new element, insert it into the -heap if it is not smaller than the minimum element of that heap; otherwise, insert it into the -heap. After that, perform heap rebalancing to maintain the properties described above:
If the size of the -heap exceeds the size of the -heap, move the largest element from the -heap to the -heap.
If the size of the -heap exceeds the size of the -heap by more than one element, move the smallest element from the -heap to the -heap.
The median of the current sequence is defined as follows:
if the number of elements is odd, the median is the smallest element of the -heap
if the number of elements is even, the median is equal to the arithmetic mean of the smallest element of the -heap and the largest element of the -heap.
Inserting an element into a heap and the subsequent rebalancing are performed in O(log_2n) time. Thus, the total running time of the algorithm is O(nlog_2n).
Example
Let us consider the process of computing the median as numbers are received sequentially. For clarity, we'll assume that after each new number is added, the sequence is sorted. Under each sequence, the corresponding median value is shown.
After processing all elements of the example, the final state of the heaps will be as follows:
Since the number of elements is odd, the median is equal to the smallest element of the -heap, i.e. .
Let the next incoming number be . Since it is not smaller than the minimum element of the -heap, add it to the -heap. After that, the size of the -heap becomes two elements larger than the size of the -heap, so we need to rebalance: move the smallest element of the -heap () to the -heap. In other words, remove from the -heap and insert it into the -heap.
Now the total number of elements in the array is even, so the median is defined as the arithmetic mean of the smallest element of the -heap () and the largest element of the -heap (), i.e. (35 + 4) / 2 = 19. In this problem, only the integer part of the median is required to be printed.
Algorithm implementation
Declare the -heap mMinHeap and -heap mMaxHeap.
priority_queue<int, vector<int>, greater<int> > mMinHeap;
priority_queue<int, vector<int>, less<int> > mMaxHeap;Initialize the heaps. In the variable , store the number of input values received. For convenience, initialize the heaps with dummy elements.
mMaxHeap.push(-MAX); mMinHeap.push(MAX);
c = 1;Process the next incoming number.
while(scanf("%d",&n) == 1)
{ Depending on the value of , insert it into one of the heaps.
if (n >= mMinHeap.top()) mMinHeap.push(n);
else mMaxHeap.push(n);If the size of the -heap exceeds the size of the -heap, or if the size of the -heap is more than one element larger than the size of the -heap, perform rebalancing.
if(mMaxHeap.size() > mMinHeap.size())
{ Move the largest element from the -heap to the -heap.
mMinHeap.push(mMaxHeap.top());
mMaxHeap.pop();
} else
if(mMaxHeap.size() + 1 < mMinHeap.size())
{ Move the smallest element of the -heap into the -heap.
mMaxHeap.push(mMinHeap.top());
mMinHeap.pop();
}Depending on whether the number of elements in the array is even or odd, print the value of the median.
if (c % 2) printf("%d\n",mMinHeap.top());
else printf("%d\n",(mMinHeap.top() + mMaxHeap.top())/2);
c++;
}