0

I am working on to find the kth smallest element in min heap. I have got a code for this whose complexity is O(k log k). I tried to improve it to O(k).
Below is the code.

 struct heap{
      int *array;
      int count;
      int capacity;
 };

 int kthsmallestelement(struct heap *h,int i,int k){
      if(i<0||i>=h->count) 
         return INT_MIN;
      if(k==1)
        return h->array[i];
      k--;
      int j=2*i+1;
      int m=2*i+2;
      if(h->array[j] < h->array[m])
      {
         int x=kthsmallestelement(h,j,k);
         if(x==INT_MIN)
            return kthsmallestelement(h,m,k);
         return x; 
      }
      else
      {
           int x=kthsmallestelement(h,m,k);
           if(x==INT_MIN)
                return kthsmallestelement(h,j,k);
            return x;
      }
 }

My code is traversing k elements in heap and thus complexity is O(k). Is it correct?

Vasu Dev Garg
  • 121
  • 1
  • 15
  • 1
    The Frederickson algorithm solves this, but it is way more complicated, and probably has huge constant factors: http://www.sciencedirect.com/science/article/pii/S0890540183710308 – Niklas B. Jul 08 '15 at 11:40
  • No, your code is NOT traversing any elements, so it has no complexity. – CiaPan Jul 08 '15 at 11:52
  • Why are you decrementing k immediately before declaring and assigning k again ? Why does kthsmallestelement have 3 arguments, and you call it with only 2 ? Does this code even compile ? – gen-y-s Jul 08 '15 at 13:06
  • @gen-y-s No, it doesn't. It fails as soon as the `struct heap` declaration, which lacks the terminating semicolon (not to mention the function type `int`, which was glued to the function name until I inserted the space). That's why I said the code does NOT traverse anything. – CiaPan Jul 08 '15 at 14:05

1 Answers1

2

Your code, and in fact, its entire approach - are completely wrong, IIUC.

In a classic min-heap, the only thing you know is that each path from the root to the children is non-decreasing. There are no other constraints, in particular no constraints between the paths.

It follows that the k-th smallest element can be anywhere in the first 2k element. If you are just using the entire heap's array built & maintained using the classic heap algorithm, any solution will necessarily be Ω(min(n, 2k)). Anything below that will require additional requirements on the array's structure, an additional data structure, or both.

Ami Tavory
  • 74,578
  • 11
  • 141
  • 185
  • You can use the binary heap's structure for O(klogk) solution, by creating a new min-heap, place the head in it (with pointer to the actual element), and for k steps: extract the top, and insert its two children instead. This is done in O(klogk) since the heap never grows more than `k` elements, and each operation is logarithmic in its size, giving a solution more optimal than the lower bound you mentioned, for k << n – amit Jul 08 '15 at 11:55
  • If I remember correctly, I've also seen an O(k) solution, but that was way too complex for me to remember what's going on. – amit Jul 08 '15 at 11:57
  • @amit Is it the article referenced in the comment by Niklas B.? – Ami Tavory Jul 08 '15 at 12:00
  • Yes seems like it. And of course, the "trivial" O(klogk) solution – amit Jul 08 '15 at 12:27
  • @amit If *k* is known in advance, then there's a trivial O(1) solution as well, no? Just use a combination of a heap and a balanced tree restricted to size *k*. Modifications are still *log(n)*, and lookup is O(1). – Ami Tavory Jul 08 '15 at 12:30
  • I need to go through it again then, but the O(klogk) does not need to know k in advance. – amit Jul 08 '15 at 12:37