如何解决“稳定” k最大元素算法
相关:priority queue with limited space: looking for a good algorithm
我正在寻找一种算法,该算法可从列表中返回最大k个元素,但不会更改最大k个元素的顺序,例如对于k=4
并给定5,9,1,3,7,2,8,4,6
,算法应返回9,6
。
更多背景信息,我的输入数据大约为200对(distance,importance)
,它们以distance
的顺序排序,我需要选择其中32个最重要的对。在这里性能至关重要,因为我必须运行这种选择算法数千次。
到目前为止,我有以下两个想法,但似乎都不是最好的。
我需要用C ++实现此功能,因此,如果有人想编写一些代码并且不知道使用哪种语言,则可以选择C ++。
解决方法
使用基于堆的算法来查找k的最大值,即使用永远不会超过 k 大小的 min 堆(而不是最大堆)。一旦超过该大小,请继续从根中拉出根,以将其恢复为 k 的大小。
最后,堆的根为 k 最大值。我们称它为 m 。
然后您可以再次扫描原始输入以收集至少等于 m 的所有值。这样,您就可以按原始顺序使用它们。
如果该 m 不是唯一的,则您可能收集了太多的值。因此,请检查结果的大小,并确定结果比 k 长多少。向后浏览该列表,并将值 m 的标记为已删除,直到达到正确的大小为止。最后收集未删除的项目。
所有这些扫描都是 O(n)。最昂贵的步骤是第一个步骤: O(nlogk)。
,受 @trincot 解决方案的启发,我对工作实现提出了一个略有不同的变化。
算法
-
使用 Floyd算法来构建最大堆,或等效于使用传递整个数组/向量的构造函数在C ++中构建 priority_queue 一次,而不是单独添加元素。如果内置O(N)时间复杂度,则为最大堆。
-
现在,将最大堆中的项目弹出K-1次,直到获得第K个最大重要性项目。将第K个最大重要性项的值存储在变量
Kth_Max_Importance_Item
中。 -
从原始输入中扫描其重要性值大于
Kth_Max_Importance_Item
的重要性值的所有节点,并将其推入输出向量。 -
通过从
Kth_Max_Importance_Item
中减去输出向量的当前大小,计算重要性值等于k
的重要性项的所需项目的剩余计数。将其存储在变量left_Over_Count
中。 -
从原始输入中扫描
left_Over_Count
个项目的数量值,如果该项目的重要性值等于Kth_Max_Importance_Item
的重要性值,则将其推入输出向量。
注意::如果importance
值不是唯一的,则可以通过 step 3 和 4 。
时间复杂度:O(N + K * log(N))。假设K
实施:
#include <iostream>
#include <vector>
#include <queue>
#include <math.h>
typedef struct Item{
int distance;
double importance;
}Item;
struct itemsCompare{
bool operator() (const Item& item1,const Item& item2){
return ((item1.importance < item2.importance) ? true : false);
}
};
bool compareDouble(const double& a,const double& b){
return (fabs(a-b) < 0.000001) ? true : false;
}
int main(){
//Original input
std::vector<Item> items{{10,2.1},{9,2.3},{8,2.2},{7,{6,1.5}};
int k = 4;
//Min Heap
std::priority_queue<Item,std::vector<Item>,itemsCompare> maxHeap (items.begin(),items.end());
//Checking if the order of original input is intact
/*for(int i=0;i<items.size();i++){
std::cout<<items[i].distance<<" "<<items[i].importance<<std::endl;
}*/
//Pulling the nodes until we get Kth Max Importance Node
int count = 0;
while(!maxHeap.empty()){
if(count == k-1){
break;
}
maxHeap.pop();
count++;
}
Item Kth_Max_Importance_Item = maxHeap.top();
//std::cout<<Kth_Max_Importance_Item.importance<<std::endl;
//Scanning all the nodes from original input whose importance value is greater than the importance value of Kth_Max_Importance_Item.
std::vector<Item> output;
for(int i=0;i<items.size();i++){
if(items[i].importance > Kth_Max_Importance_Item.importance){
output.push_back(items[i]);
}
}
int left_Over_Count = k - output.size();
//std::cout<<left_Over_Count<<std::endl;
//Adding left_Over_Count number of values of items whose importance value if equal to importance value of Kth_Max_Importance_Item
for(int i=0;i<items.size();i++){
if(compareDouble(items[i].importance,Kth_Max_Importance_Item.importance)){
output.push_back(items[i]);
left_Over_Count--;
}
if(!left_Over_Count){
break;
}
}
//Printing the output:
for(int i=0;i<output.size();i++){
std::cout<<output[i].distance<<" "<<output[i].importance<<std::endl;
}
return 0;
}
输出:
9 2.3
8 2.2
7 2.2
10 2.1
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。