-
-
Save jeryini/a26276d2289878bd7744 to your computer and use it in GitHub Desktop.
| package com.jernejerin.traffic.helper; | |
| import java.util.Comparator; | |
| import java.util.PriorityQueue; | |
| import java.util.Queue; | |
| // Given a stream of unsorted integers, find the median element in sorted order at any given time. | |
| // http://www.ardendertat.com/2011/11/03/programming-interview-questions-13-median-of-integer-stream/ | |
| public class MedianOfIntegerStream { | |
| public Queue<Integer> minHeap; | |
| public Queue<Integer> maxHeap; | |
| public int numOfElements; | |
| public MedianOfIntegerStream() { | |
| minHeap = new PriorityQueue<Integer>(); | |
| maxHeap = new PriorityQueue<Integer>(10, new MaxHeapComparator()); | |
| numOfElements = 0; | |
| } | |
| public void addNumberToStream(Integer num) { | |
| maxHeap.add(num); | |
| if (numOfElements%2 == 0) { | |
| if (minHeap.isEmpty()) { | |
| numOfElements++; | |
| return; | |
| } | |
| else if (maxHeap.peek() > minHeap.peek()) { | |
| Integer maxHeapRoot = maxHeap.poll(); | |
| Integer minHeapRoot = minHeap.poll(); | |
| maxHeap.add(minHeapRoot); | |
| minHeap.add(maxHeapRoot); | |
| } | |
| } else { | |
| minHeap.add(maxHeap.poll()); | |
| } | |
| numOfElements++; | |
| } | |
| public Double getMedian() { | |
| if (numOfElements%2 != 0) | |
| return new Double(maxHeap.peek()); | |
| else | |
| return (maxHeap.peek() + minHeap.peek()) / 2.0; | |
| } | |
| public void removeNumberFromStream(Integer num) { | |
| // if it is greater then maximum on left, then | |
| // the number must be on right side (minimum heap) | |
| if (num > maxHeap.peek()) { | |
| if (minHeap.remove(num)) { | |
| numOfElements--; | |
| // if the number of elements is not odd | |
| // after delete, then we need to move | |
| // element from max heap to min | |
| if (numOfElements % 2 == 0) { | |
| minHeap.add(maxHeap.poll()); | |
| } | |
| } | |
| } | |
| else { | |
| if (maxHeap.remove(num)) { | |
| numOfElements--; | |
| // if the number of elements is not even | |
| // after delete, then we need to move | |
| // element from min heap to max | |
| if (numOfElements % 2 != 0) { | |
| maxHeap.add(minHeap.poll()); | |
| } | |
| } | |
| } | |
| } | |
| private class MaxHeapComparator implements Comparator<Integer> { | |
| @Override | |
| public int compare(Integer o1, Integer o2) { | |
| return o2 - o1; | |
| } | |
| } | |
| public static void main(String[] args) { | |
| MedianOfIntegerStream streamMedian = new MedianOfIntegerStream(); | |
| streamMedian.addNumberToStream(1); | |
| System.out.println(streamMedian.getMedian()); // should be 1 | |
| streamMedian.addNumberToStream(5); | |
| streamMedian.addNumberToStream(10); | |
| streamMedian.addNumberToStream(12); | |
| streamMedian.addNumberToStream(2); | |
| System.out.println(streamMedian.getMedian()); // should be 5 | |
| streamMedian.addNumberToStream(3); | |
| streamMedian.addNumberToStream(8); | |
| streamMedian.addNumberToStream(9); | |
| System.out.println(streamMedian.getMedian()); // should be 6.5 | |
| streamMedian.removeNumberFromStream(9); | |
| System.out.println(streamMedian.getMedian()); // should be 5 | |
| streamMedian.removeNumberFromStream(8); | |
| streamMedian.removeNumberFromStream(3); | |
| System.out.println(streamMedian.getMedian()); // should be 5 | |
| } | |
| } |
I have written this one, but i cannot complete those two lines; also I am not sure about the time complexity. Do you think it is O(logn) for removal?
public void removal(int num){
if(num == maxHeap.peek()){
maxHeap.remove();
numberOfElements--;
return;
}
if(num == minHeap.peek()){
minHeap.remove();
numberOfElements--;
return;
}
if(numberOfElements % 2 == 0){
int median = (maxHeap.peek() + minHeap.peek())/2;
if(num < median){
// should be removed from maxheap, but how????
// ?????
// before: maxHeap: N & minheap: N - Now: maxHeap: N-1 & minheap: N
// So, one element from minheap should add to maxheap
maxHeap.add(minHeap.remove());
// Now: maxHeap: N & minheap: N-1, so it's fine
}else{
// should be removed from minheap, but how????
// ?????
// before: maxHeap: N+1 & minheap: N - Now: maxHeap: N+1 & minheap: N-1
// So, one element from maxheap should add to minheap
maxHeap.add(minHeap.remove());
// Now: maxHeap: N & minheap: N, so we are fine
}
}else{
int median = maxHeap.peek();
if(num < median){
// should be removed from max heap
}else{
// should be removed from min heap
}
}
numberOfElements--;
}Here discussed same question, but not 'delete', it is 'delete median', which is possible in O(logn). what do you think?
http://www.cs.cmu.edu/afs/cs/academic/class/15750-s11/www/hw/hw1-sol.pdf
The logic goes like that. First we need to check if the number that we want to remove is greater than the root element of the max heap. If it is, than we need to try to remove it from the min heap, otherwise we remove from max heap. Keep in mind that min and max heap are implemented as PriorityQueue, which means that removal of specified object is done in linear time. If the removal is successful we need to check for the number of elements in heap and fix it.
Also watch out what the paper you linked states. It says the following:
deleteMedian(D): Delete the median of D in time O(log n).
They only want to delete the median of structure D, where in my case the user can remove arbitrary number from stream. I see you are trying to implement the removal of only median element, as it is stated in the paper. Just follow the solution specified in the paper. Will take a look at your code later, as I am currently busy.
Thanks for explanation 👍
Hi - is it possible to public this under an ASF 2.0 license?
Here is a little cleaner and little more optimized version of addNumberToStream():
public void addNumberToStream(Integer num) {
if (numOfElements % 2 == 0) {
maxHeap.add(num); //no more need for minHeap.isEmpty() check
} else {
minHeap.add(num); //no more need for maxHeap.poll()
if (maxHeap.peek() > minHeap.peek()) {
Integer maxHeapRoot = maxHeap.poll(); //only one variable is needed for swap
maxHeap.add(minHeap.poll());
minHeap.add(maxHeapRoot);
}
}
numOfElements++; //only need one numOfElements++
}
Could you please briefly explain how your removal works?