当前,我在数据结构上遇到问题,并且我有一个问题,我必须在数组中找到第k个最大元素。实际的问题在这里: https://www.geeksforgeeks.org/kth-smallestlargest-element-unsorted-array/。
我使用堆以两种不同的方式来解决这个问题,第二种是使用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;
但是我的地图解决方案给出了超过时间限制。根据我的说法,地图解决方案的时间复杂度为(n + klog(n)),与堆解决方案相同。 那么为什么地图解决方案会赋予TLE?
答案 0 :(得分:0)
没有看到您的堆版本,我猜想映射的分配是造成麻烦的原因。每个节点都需要分配,这意味着有一个锁和一些其他管理。
并且您必须在map数据结构中内部遵循指针,而在堆中通常不是这种情况。
使用大O表示法不会增加任何时间,但实际上每个操作都会使程序运行速度大大降低。
答案 1 :(得分:0)
使用映射的解决方案的时间复杂度为O(k + nlog(n))。每次插入std::map
都会花费log(n)时间,而您正在执行'n'插入。单独插入的时间复杂度将花费O(nlog(n))时间。
有关将元素插入std::map
的更多信息,请参见http://www.cplusplus.com/reference/map/map/insert/。
答案 2 :(得分:0)
对该算法的简单改进是有一个“技巧”: *如果只需要打印“ k”个元素,则只需记住“ k”个最大元素。这样,插入操作就不会超过O(log k)而不是O(log n)。而且k大概比n小得多。
因此,与其将所有内容插入到越来越大的地图中(而且越来越慢-您提到时间限制),不如将其插入地图。更改代码以一次删除地图中的最小元素(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()) // <<<<<<<<
}
}