时间限制超过最大堆
Time Limit Exceed about max heap
我想设计一个功能,以在一组无序的n个元素中找到k最大的元素,并具有时间复杂性:在线法官上的 Θ(N+klogN)
。
这是一个样本:
输入
LN 1 : N K
LN 2 : N numbers
输出
LN 1 : K biggest number
LN 2 : Final heap
样品输入
10 4
17 19 26 37 30 11 5 29 32 1
样本输出
29
26 19 11 17 1 5
这是我的代码:
#include <iostream>
using namespace std;
int main(){
int i,j,rc,temp,temp1,length,K;
cin>>length>>K;
int *heap = new int[length];
for(i=0;i<length;i++) cin>>heap[i];
for(i=length/2-1;i>=0;i--){ //build a max heap first with Θ(N)
while(!((i>=length/2)&&(i<length))){
j = 2*i+1;
rc = 2*i+2;
if((rc<length)&&(heap[j]<heap[rc])) j=rc;
if(heap[i]>heap[j]) break;
temp = heap[i];
heap[i]=heap[j];
heap[j]=temp;
i=j;
}
}
int k,n=length;
for(k=0;k<K;k++){ //shiftdown k times to find k biggest
temp1=heap[--n]; //numbers with Θ(klogN)
heap[n] = heap[0];
heap[0] = temp1;
if(n!=0) {
i=0;
while(!((i>=n/2)&&(i<n))){
j = 2*i+1;
rc = 2*i+2;
if((rc<n)&&(heap[j]<heap[rc])) j=rc;
if(heap[i]>heap[j]) break;
temp = heap[i];
heap[i]=heap[j];
heap[j]=temp;
i=j;
}
}
}
cout<<heap[length-K]<<endl;
for(i=0;i<length-K;i++)
cout<<heap[i]<<" ";
return 0;
}
没关系,但是数据之一超过了时间限制,我对如何解决此问题感到非常困惑。
您的筛选操作似乎不正确。那里不应该有两个嵌套环。您应该只是从根本上开始,并继续与其中一个孩子交换,直到它比这两个孩子大。外循环for(i=n/2-1;i>=0;i--)
不应该在那里(这会导致每个筛分降低O(n)
) - 我认为您应该将i
设置为0。
编辑:您的堆操作也太慢了:您正在使用相同的循环变量i
用于外部和内部循环,因此它会交替生长更大和较小。内环应从外循环的i
开始,但不应影响外环的下一次迭代中i
的值。我建议将筛选操作放在自己的功能中。这既可以解决此问题,又避免对筛选两次编码。
我猜一些在线judge.org竞赛。您为什么不共享问题链接?
那么,我们可能可以分辨您是否真的需要Heapsort,或者您是否会更好地使用QuickSelect和良好的启发式方法。
我的猜测是,普通的heaport将在其测试用例之一中不够。
您可能还需要添加优化,例如在开始和结束时检查预分类数据或反向排序的数据(和数据部分)。避免为这些部分构建堆,但要保持原样。
尝试在巨大 reverse 排序列表上运行heapsort ,带有大k,iirc,这是一个最坏的情况(对于最大速度,任何米哈最糟糕的情况,反之亦然)。
典型的在线法官测试案例通常是围绕这种已知最坏情况的精心设计的。然后设置时间限制,以便即使使用非常好的优化O(n + k log n)
解决方案,您将丢失的解决方案与真正的O(n)
解决方案相比。他们只需要使K足够大。他们来自比赛,他们想通过给他们真正的均值输入文件来挑战他们!
P.S。您 HEAP BUILD 似乎也太复杂了。问题是您再次增加i
。您不需要这样做。通过在同时循环中增加I,您会导致自下而上的堆构造再次"重新启动"多次"重新启动"。因此,您的堆构建可能不再是O(n)
。
您可能想检查三个差异序列发生的事情:
-
- 4 2 1 2 3 4
-
- 4 2 4 3 2 1
-
- 4 2 1 1 1 1
int NN=0;
for(i=length/2-1;i>=0;i--){ //build a max heap first with Θ(N)
cout << "i=" << i << "n";
while(!((i>=length/2)&&(i<length))){
j = 2*i+1;
rc = 2*i+2;
cout << NN++ << " " << j << " " << rc << " " << i << "n";
if((rc<length)&&(heap[j]<heap[rc])) j=rc;
if(heap[i]>heap[j]) break;
temp = heap[i];
heap[i]=heap[j];
heap[j]=temp;
i=j;
}
}
在最后一个情况下,环将稳定为j = 3;RC = 4;i = 1;
也许内部循环应该使用单独的变量代替" i"。
- C++为构建时间获取QDateTime的可靠方法
- 从持续时间构造std::chrono::system_clock::time_point
- 向量 <int> a {N, 0} 和 int arr a[N] = {0} 的时间复杂度有什么区别
- while循环中while循环的时间复杂度是多少
- 使用简单类型列表实现的指数编译时间.为什么
- 是否可以在编译时初始化数组,以便在运行时不会花费时间?
- 在已经使用Git的情况下减少编译时间
- 有没有一种方法可以创建一个带有哈希表的数据库,该哈希表具有恒定时间查找功能
- 如何将包含epoch时间的十六进制字符串转换为time_t
- 从文本文件中读取时钟时间和事件时间并进行处理
- 具有未知值时的时间复杂性
- 如何减少花费的时间
- C++在变量给定的指定时间内关闭电脑
- rcpp函数中的清理时间很长
- C++:floor unix时间戳到UTC月份
- 如何在c++中录制具有精确帧时间戳的视频
- 在两台机器之间进行时间戳的最佳c++chrono函数是什么
- KMP算法和LPS表构造的运行时间
- 为什么std::互斥需要很长的、非常不规则的时间来共享
- 使用Boost Interprocess创建托管共享内存需要很长时间