-5

currently i am doing problem on data structure and i have a question in which i have to find kth largest element in an array. the actual problem is here: https://www.geeksforgeeks.org/kth-smallestlargest-element-unsorted-array/.

i did this question in two different way using heap and second is using map.

my solution using map.

   int t;
cin>>t;
while(--t>=0){
int n,k;
cin>>n;
vector<int> A(n);
for(int i=0;i<n;i++){
cin>>A[i];
 }
cin>>k;
map<int,int> m;
for(int i=0;i<n;i++){
    m[A[i]]++;
}
auto it=m.begin();
for(int i=1;i<=k-1;i++){
    it++;
}
cout<<it->first<<endl;

but my map solution is giving Time Limit Exceeded. according to me map solution also has a time complexity of (n+klog(n)), same as heap solution. so why is map solution giving TLE?

melpomene
  • 79,257
  • 6
  • 70
  • 127
  • I have an answer for this. Vote to repopen as it seems pretty obvious what the question is. Which is better a std::map or a heap data structure. – Martin York May 30 '19 at 07:31
  • The problem here is both methods have a complexity of O(n.log(n)). The trouble is map uses allocations per item while a heap implementation usually uses a vector and thus less allocations. Thus the problem is the overhead of memory manegment. So the heap implementation should be significantly more efficient (assuming a few things: 1: You know the number of elements before hand 2: The cost of moving the elements does not outway the cost of memory mangement). – Martin York May 30 '19 at 07:33
  • There is another way to do it. Check out [Quickselect](https://en.wikipedia.org/wiki/Quickselect), which is O(n). – Jim Mischel May 30 '19 at 17:04
  • The heap selection algorithm has time complexity (n * log(k)), where n is the total number of items. k is the item you want to select (i.e. the kth item). – Jim Mischel May 30 '19 at 18:01

3 Answers3

0

Without seeing your heap version I would guess the map's allocation is the cause of the trouble. Each node needs an allocation, which implies a lock and some additional management.

And you have to follow the pointers internally in the map data structure, which is usually not the case in heaps.

In big O notation this doesn't add anything to the time, but in practice each can slow down the program by a large factor.

Surt
  • 13,762
  • 3
  • 21
  • 34
  • Heap "Data Structure" is usually implemented in an array or vector. [std::make_heap()](http://www.cplusplus.com/reference/algorithm/make_heap/) [std::push_heap](http://www.cplusplus.com/reference/algorithm/push_heap/) [std::sort_heap](http://www.cplusplus.com/reference/algorithm/sort_heap/) – Martin York May 30 '19 at 07:23
0

The time complexity for your solution using maps would be O(k + nlog(n)). Each insertion into std::map takes log(n) time and you are performing 'n' insertions. Time complexity for insertion alone would take O(nlog(n)) time.

See http://www.cplusplus.com/reference/map/map/insert/ for more information about inserting elements into std::map.

Vishnu Dasu
  • 441
  • 5
  • 16
  • Inserting an element into a heap data structure is also `O(log(n))`. So inserting n elements is `O(n.log(n))` for a heap as well. – Martin York May 30 '19 at 07:26
  • Insertion of elements into a heap can be done in linear time. See [this](https://stackoverflow.com/questions/9755721/how-can-building-a-heap-be-on-time-complexity) answer for the derivation of time complexity for insertion into a heap. – Vishnu Dasu May 30 '19 at 07:33
  • See: [std::push_heap()](http://www.cplusplus.com/reference/algorithm/push_heap/) who's complexity is `O(log(n))`. – Martin York May 30 '19 at 07:37
  • Assuming he's referring to the algorithm in the link provided in the question insertion would take linear time. – Vishnu Dasu May 30 '19 at 07:43
  • Don't see that. When the documentation for the implementation clearly states it will take `O(log(n))`. – Martin York May 30 '19 at 07:49
  • The algorithm does not use use `std::push_heap()`. They've used their own user defined functions for insertion. – Vishnu Dasu May 30 '19 at 07:58
  • I see that now. Yep you can improve on the basic implementation. – Martin York May 30 '19 at 09:15
  • Insertion into a heap has *worst case* time complexity of O(log n). Average case is O(1), as discussed in https://stackoverflow.com/q/39514469/56778. As Vishnu pointed out, there is an O(n) algorithm for putting an array into heap order in-place, but that's not really "inserting" items into a heap. – Jim Mischel May 30 '19 at 18:13
0

A simple improvement to the algorithm is that there is a "trick": * If you only need to print "k" elements, then you only need to remember the "k" biggest elements. That way the insert operations never exceed O(log k) rather than O(log n). And k is presumably much less than n...

So instead of inserting everything into a map that gets bigger and bigger (and slower and slower - you mention a time-restriction). Change the code to remove the smallest element in the map once (map.size() >= k):

    map<int,int> m;
    for(int i = 0; i < n ; i++) {
        m[A[i]]++;
        if(m.size() > k) {           // <<<<<<<<
             m.erase(m.begin())      // <<<<<<<<
        }
    }

z80
  • 1