-1

We have array arr with n distinct elements. we want to fill D[i] be median of numbers arr[1] to arr[i]. it can done efficiently in O(n log n).

Is there any effective way that we do this work?

  • If you already know that it can be done in O(n log n) what is the question then? Do you expect an even more efficient way? – MrSmith42 Nov 24 '20 at 07:33
  • The Median is the ***"middle"*** of a sorted list of numbers *(ref: [MathsIsFun](https://www.mathsisfun.com/median.html))*. So sort the array and pick the middle value. Sorting is _O(n log n)_. --- For _O(n)_ solution, see e.g. [Selection algorithm](https://en.wikipedia.org/wiki/Selection_algorithm) on Wikipedia. – Andreas Nov 24 '20 at 07:34
  • What have **YOU** tried / researched so far? Share **YOUR** code / findings. – MrSmith42 Nov 24 '20 at 07:34
  • @Andreas we should fill the array D from index 0 to n for example D[0] contains meidan of elements array[0] to array[0]. D[1] contains meidan of elements array[0] to array[1]. D[2] contains meidan of elements array[0] to array[2]... –  Nov 24 '20 at 07:41
  • @MrSmith42 i want to understand logic. how we can reach to this time? what is the method? –  Nov 24 '20 at 07:41
  • 2
    @JohnatanMorian Your question is unclear. Are u looking for a O(nlogn) solution or a more optimal one? – Serial Lazer Nov 24 '20 at 07:54
  • You didn't explain what *D* is and how *n* is involved in the algorithm. – akuzminykh Nov 24 '20 at 08:17
  • @SerialLazer both of them. at first I want to find this is lower bound? is there any more efficient version? if yes what? if no, how this lower bound can be reached (what is the algorithm)? –  Nov 24 '20 at 09:51
  • @akuzminykh D is another array, we want to fill this array with median of numbers in array a in such order that i descirbed. –  Nov 24 '20 at 09:52

2 Answers2

0

Supposing that array arr is already sorted in increasing order, the following code fills array D, where for each i, D[i] is the median of values (arr[0], ..., arr[i]).

// uncomment line below if arr is not sorted
// Arrays.sort(arr);

for (int i = 0, i < arr.length; i++)
{
    if (i % 2 == 0) {
        
        // calculate median for array with odd length
        D[i] = arr[i/2];
    }
    else {
        
        // calculate median for array with even length
        D[i] = (arr[i/2] + arr[i/2 + 1]) / 2;
    }  
}

Complexity: The time complexity for the above algorithm is O(n).

In case the initial array is not sorted and we have to sort it, this add time complexity O(nlogn). The final time complexity is O(nlogn + n) = O(nlogn)

Evris Tzam
  • 178
  • 9
0

Theta(n log n) complexity approach:

Make two heaps - maximal heap and minimal heap

Walk through array a and insert every element in two-heaps data structure.

If element is larger than currend median, add it to minimal heap (it contains larger elements), otherwise add it to maximal heap (with smaller elements)

Keep heaps of (almost) equal size ((k+1)/2 and k/2 at k-th step), moving top element into another heap if needed.

Median element of current slice is at the top of the larger heap

I hope it is enough to have these clues to implement.

Java (I've had to learn a bit ;))

public static void main (String[] args) throws java.lang.Exception
{  Integer[] arr= {10,70,4,15,20,12,8,17};
   PriorityQueue<Integer>maxheap = new PriorityQueue<>(10, Collections.reverseOrder());
   PriorityQueue<Integer>minheap = new PriorityQueue<>(10);
   Integer median = -9999;
   for (Integer a: arr) {
      if (a >= median) {
         minheap.add(a);
         if (minheap.size() - maxheap.size() >= 2)
             maxheap.add(minheap.poll());
      }
        else {
         maxheap.add(a);
         if (maxheap.size() - minheap.size() >= 2)
             minheap.add(maxheap.poll());
        } 
        Integer diff = maxheap.size() - minheap.size();
        if (diff == 1)
             median = maxheap.peek();
        else if (diff == -1)
           median = minheap.peek();
        else   
            median = Math.min(minheap.peek(), maxheap.peek());
        System.out.println(median);
   }
}

Python implementation (first done). Minus is used to provide correct ordering of max heap (Python heapq is minimal heap) without additional comparator.

import heapq

arr=[10,70,4,15,20,12,8,17]
print(arr)
d = []
ds = []
minheap = []
maxheap = []
median = -99999
for i in range(len(arr)):
    sli = arr[:i+1]
    sli.sort()
    ds.append(sli[(len(sli) - 1)//2])

    if arr[i] >= median:
        heapq.heappush(minheap, arr[i])
        if len(minheap) - len(maxheap) >= 2:
           heapq.heappush(maxheap, -heapq.heappop(minheap))
    else:
        heapq.heappush(maxheap, -arr[i])
        if len(maxheap) - len(minheap) >= 2:
           heapq.heappush(minheap, -heapq.heappop(maxheap))

    diff = len(maxheap) - len(minheap)
    if diff == 1:
        median = -maxheap[0]
    elif diff == -1:
        median = minheap[0]
    else:
        median = min(minheap[0], -maxheap[0])
    d.append(median)

print(ds) #dumb method to compare
print(d)

>>>[10, 10, 10, 10, 15, 12, 12, 12]
>>>[10, 10, 10, 10, 15, 12, 12, 12]
MBo
  • 77,366
  • 5
  • 53
  • 86
  • A more in-depth explanation of that algorithm: https://stackoverflow.com/a/15319593/4000124 – Evris Tzam Nov 24 '20 at 09:00
  • my concerns is about time complexity. there is the lower bound am I right? –  Nov 24 '20 at 09:49
  • This approach provides `Theta(n log n)` complexity (so complexity cannot be larger or (I think) smaller) – MBo Nov 24 '20 at 10:04
  • wow, where is wrong? suppose arr=[10,70,4,15,20,12,8,17]. we insert simultaneously one by one in max and min heap. min heap root is 10, left be 70, up to yet median of two first element is root of mean heap. when 4 comes, root of mean heap change to 4 but median of first three element is 10 !!!! where am I wrong? –  Nov 25 '20 at 20:25
  • No, we insert elements into one heap (say maximal - note it contains smaller elements). When `maxheapsize - minheapsize >=2` occurs, we move top element of max heap into min heap (so size becomes equal).Top element of max heap is median. For your example max heap at the third step [10,4], min heap [70], median 10. After 8 steps maxheap [12,10,4,8], minheap [15,17,20,70]. – MBo Nov 25 '20 at 20:56
  • @MBo thanks. a last tips: at step 3: max heap [10,4], min heap [70], at step 4: 15 comes to max heap -- > max heap [15, 4, 10] then difference with min heap be 2 then move 15 to min heap [15, 70] and max heap [10, 4] then we write median of max heap (10) in to D[i]. but at this step your algorithm move 15 to another heap before writing to array D. as we know final D=[10, 10, 10, 10, 15, 12, ...] and we have median 15 in D[i] but at this step we forward 15 to another heap before filling D ? would you please tell me how D[i] is fill in step 4 and 5 here? –  Nov 26 '20 at 03:21
  • In array of even length median might be chosen from A[n/2] and A[n/2+1]. If you want - get top of another heap when length is even. – MBo Nov 26 '20 at 03:33
  • please clear comments so messy –  Jan 09 '21 at 23:31