The task is to implement a queue in java with the following methods:
- enqueue //add an element to queue
- dequeue //remove element from queue
- peekMedian //find median
- peekMinimum //find minimum
- peakMaximum //find maximum
- size // get size
Assume that ALL METHODS ARE CALLED In EQUAL FREQUENCY, the task is to have the fastest implementation.
My Current Approach:
Maintain a sorted array, in addition to the queue, so enqueue and dequeue are take O(logn) and peekMedian, peekMaximum, peekMinimum all take O(1) time.
Please suggest a method that will be faster, assuming all methods are called in equal frequency.
Well, you are close – but there is still something missing, since inserting/deleting from a sorted array is
O(n)(because at probability 1/2 the inserted element is at the first half of the array, and you will have to shift to the right all the following elements, and there are at least n/2 of these, so total complexity of this operation isO(n)on average + worst case)However, if you switch your sorted DS to a skip list/ balanced BST – you are going to get
O(logn)insertion/deletion andO(1)minimum/maximum/median/size (with caching)EDIT:
You cannot get better then
O(logN)for insertion (unless you decrease thepeekMedian()toOmega(logN)), because that will enable you to sort better thenO(NlogN):First, note that the median moves one element to the right for each "high" elements you insert (in here, high means >= the current max).
So, by iteratively doing:
you can find the "higher" half of the sorted array.
Using the same approach with
insert(MIN)you can get the lowest half of the array.Assuming you have
o(logN)(small o notation, better thenTheta(logN)insertion and O(1)peekMedian(), you got yourself a sort better thenO(NlogN), but sorting isOmega(NlogN)problem.=><=
Thus
insert()cannot be better thenO(logN), with median still beingO(1).QED
EDIT2: Modifying the median in insertions:
If the tree size before insertion is 2n+1 (odd) then the old median is at index n+1, and the new median is at the same index (n+1), so if the element was added before the old median – you need to get the preceding node of the last median – and that’s the new median. If it was added after it – do nothing, the old median is the new one as well.
If the list is even (2n elements), then after the insertion, you should increase an index (from n to n+1), so if the new element was added before the median – do nothing, if it was added after the old median, you need to set the new median as the following node from the old median.
note: In here next nodes and preceding nodes are those that follow according to the key, and index means the "place" of the node (smallest is 1st and biggest is last).
I only explained how to do it for insertion, the same ideas hold for deletion.