假设您有一架飞机,而且燃油低。除非飞机掉落3000磅的乘客体重,否则它将无法到达下一个机场。为了最大程度地挽救生命,我们希望首先将最重的人员从飞机上救出。
哦,是的,飞机上有数百万人,我们希望找到一种最佳算法来找到最重的乘客,而不必对整个列表进行排序。
这是我尝试用C ++编写代码的代理问题。我想按重量对旅客舱单进行“ partial_sort”,但我不知道我需要多少个元素。我可以实现自己的“ partial_sort”算法(“ partial_sort_accumulate_until”),但是我想知道是否有使用标准STL进行此操作的简便方法。
一种方法是使用最小堆(std::priority_queue在C ++中)。假设您有一MinHeap堂课,这是您的处理方法。(是的,我的示例在C#中。我认为您明白了。)
std::priority_queue
MinHeap
int targetTotal = 3000; int totalWeight = 0; // this creates an empty heap! var myHeap = new MinHeap<Passenger>(/* need comparer here to order by weight */); foreach (var pass in passengers) { if (totalWeight < targetTotal) { // unconditionally add this passenger myHeap.Add(pass); totalWeight += pass.Weight; } else if (pass.Weight > myHeap.Peek().Weight) { // If this passenger is heavier than the lightest // passenger already on the heap, // then remove the lightest passenger and add this one var oldPass = myHeap.RemoveFirst(); totalWeight -= oldPass.Weight; myHeap.Add(pass); totalWeight += pass.Weight; } } // At this point, the heaviest people are on the heap, // but there might be too many of them. // Remove the lighter people until we have the minimum necessary while ((totalWeight - myHeap.Peek().Weight) > targetTotal) { var oldPass = myHeap.RemoveFirst(); totalWeight -= oldPass.Weight; } // The heap now contains the passengers who will be thrown overboard.
根据标准参考,运行时间应与成正比n log k,其中n是乘客k人数,是堆上物品的最大数量。如果我们假设乘客的体重通常在100磅或以上,那么堆在任何时候都不可能容纳30多个物品。
n log k
n
k
最坏的情况是按重量从最低到最大的顺序显示乘客。这将需要将每个乘客添加到堆中,并从堆中删除每个乘客。不过,如果有100万乘客,并且假设最轻的乘客体重为100磅,那么n log k工作量就很小。
如果您随机获得乘客的体重,则性能会更好。我在推荐引擎中使用了类似的内容(我从几百万个列表中选择了前200个项目)。我通常最终只将50,000或70,000个项目实际添加到堆中。
我怀疑您会看到非常相似的东西:您的大多数候选人将被拒绝,因为他们比已有的最轻的人轻。并且Peek是一项O(1)操作。
Peek
O(1)
有关堆选择和快速选择的性能的更多信息,请参阅理论与实践相结合。简短版本:如果您选择的项目少于总项目数的1%,那么堆选择显然是快速选择的赢家。超过1%,然后使用快速选择或类似Introselect的变体。