descending heap sort - heapsort

use heap sort to sort this in descending order and show the steps or explanation please
below is the tree
79
33 57
8 25 48
below is the array
79 - 33 - 57 - 8 - 25 - 48
ok ascending is easy because the largest element is at the top we can exchange the last element and the first element and then use heapify as the sample code in wikipedia describes it.
ok let me clarify, the heap is built on the tree that I drew. I know the steps to do ascending order and the array would look like 8 - 25 - 33 - 48 - 57 - 79. but what are the steps to do descending. This is a very straight forward question. just explain the steps needed to order the array in descending order.

This looks like a max heap, so to sort in descending order is trivial:
FUNCTION descSortedFrom(Heap h) : Array
LET N := h.size
LET ret := NEW Array (size = N)
FOR i = 0..N-1 DO
ret[i] := h.deleteMax
RETURN ret
Binary heap, binomial heap, and fibonacci heap all support deleteMax on max heap (or analogously, deleteMin on min heap) in O(log N), so overall this is O(N log N), which is optimal for comparison-based sort.
Note that this uses an external storage array for simplicity. If you insist on using the same array as the heap, then simply do the ascending sort as you've done, then (guess what?) reverse the array in O(N).
An alternative solution
This is more complicated than necessary, but is one-pass and in-place. Essentially, instead of treating array elements [0..k) as your heap elements, you take [N-k..N) instead. You must modify heapify to take a starting offset to accommodate this change.
To illustrate, as you've figured out, this is how you sort in ascending order:
entire array = [ the heap elements ; the sorted asc elements ]
Essentially you build the sorted asc elements right to left, swapping the first of the heap (its max) with the last element of the heap, shrinking the heap size by one, and then heapifying the remaining heap elements.
To sort in descending order is conceptually the same:
entire array = [ the sorted desc elements ; the heap elements ]
You build the sorted desc elements left to right. The max of the heap does not need to be relocated, you simply shrink the heap size by one, but instead of cutting off at the tail, you cut off at the head. You must therefore give an offset argument to heapify so it knows where the heap elements actually start in the array.

Related

Lower bound of merging k sorted arrays of size n

As the title suggests, I am wondering what the proof for the lower bound of merging k sorted arrays of size n is? I know that the bound is O(kn*log[k]), but how was this achieved? I tried comparing to sorting an array of p elements using a decision tree but I don't see how to implement this proof.
This is pretty much easy to prove, try to think about it in a merge-sort way. To merge-sort an array of size K*N it takes O(KN*log(K*N)).
But we don't have to reach leafs of size 1, as we know when the array size is N it is sorted. For simplicity we will assume K is a power of 2.
How many times do we have to divide by 2 to reach leafs of size N ?
K times!
Visualization
So you have log(k) steps, then having to merge each step costs KN, and there are log(k) steps. Hence, the time complexity is O(NK(log(K))
Proof: Lets assume it is not a lower bound and we could achieve better. Then for any unknown array of size N*K we could split it in 2 until we reach sub-arrays of size N, merge-sort each of the arrays of size N in Nlog(N) time and in total for all the arrays K*N*log(N) time.
After having the K arrays of size N sorted, we have to merge them into a bigger array of size N*K, pay less than O(NK*(log(K)) as we assumed it is not the lower bound.
At the end you sorted an unknown array of size N*K in a complexity lesser than N*K*log(N*K) which is not possible in the comparison model.
Hence, you can't achieve better than O(NK*(log(K)) while merging the K sorted arrays of size N.
Possible implementation.
Let's create a heap data structure that store pairs (element, arrayIndex) ordered by element. Then
Add the first element of each array with the corresponding array index to this heap.
On each step, remove the top (lowest) pair p from the heap, add p.element to the result, and insert to the heap the pair (next, p.arrayIndex) with the next element from the array with p.arrayIndex index (if it is not empty).
For tracking 'next' element you need an array with k indices/pointers/iterators that are pointing to the next element of the corresponding array.
There will be at most k elements in the heap at any time, thus the insert/remove operations of the heap will have O(log(k)) complexity. Every element will be inserted and removed once from the heap. The number of elements is n*k. Overall complexity is O(n*k*log(k)).
Create a min heap of size k which stores the next item from each of the k arrays. Each node also stores which array it came from. Create your sorted array by adding the min from the heap to final_sorted_array, then adding the next element from the array that value came from to the heap.
Removing the min elt of the heap is O(log k). You have a total of NK elements so you do this NK times. Final result: O(NK log k).

how to find sum up to kth element of sorted sub-array from l to r?

Problem:
We have given an array A[] of size N. Now we have given Q queries, each queries consist of three integer l,r,k where:
1<=l<=r<=N
1<=k<=(r-l+1)
1<=N,Q<=10^5
Now,we want to find out the sum upto the k element of the sorted sub-array from l to r.
For example:
Let N=6 and array element be 5,1,7,4,6,3
And Q=1 where l,r,k be as 2,5,3.
then sub-array from index 2 to index 5 be {1,7,4,6}
after sorting it becomes as {1,4,6,7}
so sum upto k=3 term is equal to (1+4+6)=11
so answer is 11 .
I have tried using sorting of each sub-array and then sum, it takes Q*N*log(N) time complexity in worst case.
Please help to find any better solution within time complexity less than Q*N in worst case.
One approach would be to preprocess by using mergesort with the modification that we keep a copy of all the sorted intermediate results.
This preprocessing takes O(nlogn).
Suppose we started with 32 elements. We would now have:
16 sorted 2 element lists
8 sorted 4 element lists
4 sorted 8 element lists
2 sorted 16 element lists
1 sorted 32 element list.
We can also precompute the prefix sum of each of these lists in O(nlogn).
Then when faced with a query from l to r, we can identify log(n) of the preprocessed lists that together will cover all elements from l to r.
We can then use binary search to find the value such that there are exactly k smaller elements in the identified lists, and use the prefix sums to calculate the sum.
If O(Q) >= O(log N):
Sort the original array indices by the sorting order of their elements, for instance:
values: [50, 10, 20, 40, 30] -> [10, 20, 30, 40, 50]
indices: [#0, #1, #2, #3, #4] -> [#1, #2, #4, #3, #0]
Then, for each query, scan the sorted indices left to right, and add the values of the first k elements that you encounter whose indices are within range ([l, r]). The complexity will be O(QN + N log N) = O(QN) -- again, provided that O(Q) >= O(log N).
There's a way to improve on this by sorting the query ranges first, and then execute all queries in a single scan of the sorted indices, but there's no way to predict how this will affect complexity, short of knowing something special about the lengths of the ranges.

How to find the kth minimum element from a Double linked list?

I need to implement a function which can be find the kth minimum from doubly linked list.
I searched on internet and come to know about this :
quickSelect logic and k-th order statistic algorithm would be effective for array or vector but here i am using linked list where I do not have any size of linked list so its hard to divide them in 5 elements part.
My function testcase is looks like this :
for(int i = 0; i < 1000; ++i)
{
// create linked list with 1000 elements
int kthMinimum = findKthMin(LinkedList, i);
// validate kthMinimum answer.
}
Here linkedlist can be in anyorder, we have to assume randomized only.
Any idea or suggestion to find kth minimum from doubly linked list in efficient time?
Thanks
Algorithm
You can maintain a heap of size k by doing the following:
Fill the array with the k first elements of the list.
Heapify the array (using a MaxHeap)
Process the remaining elements of the list:
If top of the heap (the max) is greater than the current element in the list e, replace it with e (and maintain the heap invariant)
If the element is greater, just ignore it and carry on
At the end of the algorithm, the k-th smallest element will be at the top of the heap.
Complexity
Accumulate the first k elements + heapify the array: O(k)
Process the remaining part of the list O((n-k)ln(k)).
If the list is doubly-linked, you can run the QuickSort algorithm on it. On my experience QuickSort is the fastest sorting algorithm (measured generating random lists, and pitting it against HeapSort and MergeSort). After that, simply walk the list k-positions to get your k-th smallest element.
QuickSort average time is O(n*log(n)), walking the list will be O(k), which in its worst case is O(n). So, total time is O(n*log(n)).

Time complexity of obtaining the k smallest values overall from n sorted arrays?

I have n arrays. Each of these array can be of infinite length. (length can be variable). All these n arrays are sorted.
now I want to fetch out top k smallest elements out of these n sorted arrays.
For example n=5 and k=10
2 4 6 7 9
23 45 67 78 99
1 2 6 9 1000 4567 6567 67876
45 56 67 78 89 102 103 104
91 991 9991 99991
now answer should be 1 2 4 6 7 9 23 45 56 67
Would it be O(n*k) i.e O(n^2) in worst case, and O(k) in best case?
It's O(n + k.log(n)) I think.
First build a heap of the smallest element in each array (storing the index of the array too). Building a heap of size n is O(n). Then, repeat k times: take an element from the heap (which is O(log n)), and insert the next smallest element from the array the element you took was from (also O(log n)). Overall, this is O(n + k.log(n)).
The answer provided by Anonymous is the better solution in this case because we know that the individual arrays are sorted.
You can do it with a heap in O(n log k) time, worst case. It will require O(k) extra space.
initialize a MAX heap
for each array
for each item in the array
if (heap.count < k)
heap.insert(item)
else if (item < heap.peek())
{
// item is smaller than the largest item on the heap
// remove the smallest item and replace with this one
heap.remove_root()
heap.insert(item)
}
else
{
break; // go to next array
// see remarks below
}
Because you know that the arrays are initially sorted, you can include that final optimization I showed. If the item you're looking at is not smaller than the largest item already on the heap, then you know that no other item in the current array will be smaller. So you can skip the rest of the current array.
That's the algorithm to give you the smallest k items. If you want the largest k items, build a MIN heap and change if (item < heap.peek()) to if (item > heap.peek()). In that case, you would get better performance by walking the arrays backwards. That would reduce the number of heap insertions and removals. If you don't walk the arrays backwards, you won't be able to use the optimization I showed.
Another way to do it would be to concatenate all of the items into a single array and use Quickselect. QuickSelect is an O(n) algorithm. Empirical evidence suggests that using a heap is faster when k < .01*n. Otherwise, Quickselect is faster. Your mileage may vary, of course, and having to create a single array from the multiple arrays will add processing and memory overhead to Quickselect.

Top 5 elements in an unsorted array

An unsorted array is given and we need to find top 5 elements in an efficient way and we cannot sort the list .
My solution :
Find the max element in the array. O(n)
Delete this max element after processing/using it.
Repeat step 1 & 2 , k times ( 5 times in this case ).
Time Complexity : O(kn) / O(n) , Space Complexity : O(1).
I think we can find the max element in O(logN) , So it can be improved to O(klogN). Please correct me if I am wrong.
Can we do better than this ? Using max-heap would be inefficient I guess?
PS - This is not any homework.
If you can use an auxiliary heap (a min heap with minus element at top) you can do that in O(nlogm), where n is the list length and m the number of max elements to keep track of.
Since the aux heap has a fixed max size (5) I think that operations on that structure can be considered O(1). In that case the complexity is O(n).
Pseudo code:
foreach element in list:
if aux_heap.size() < 5
aux_heap.add(element)
else if element > aux_heap.top()
aux_heap.remove_top()
aux_head.add(element)
Using a partial quicksort we can achieve O(n), this doesn't require any auxiliary space. Using a max heap, as in the other solution requires O(n log k) time.

Resources