您可以使用最小堆或最小优先级队列(在 PHP 中略有不同)。当那个堆有k个元素时,当你找到一个比堆中的最低分数更好的条目时,交换堆的顶部元素。然后,您将得到前k个条目,得分最低的条目位于顶部。因此,作为最后一步,您将从堆中提取条目并反转它们的顺序。
这是使用 SplPriorityQueue 的外观。请注意,此结构将最大优先级值放在顶部,因此我们将为其提供负分数,因此要在堆/队列顶部获得最小分数:
function getTop($input, $k) {
$q = new SplPriorityQueue();
$q->setExtractFlags(SplPriorityQueue::EXTR_PRIORITY);
foreach ($input as $entry) {
if ($q->count() < $k) {
$q->insert($entry, -$entry["score"]); // negate score to get lower scores first
} else if ($entry["score"] > -$q->top() ) { // better score than least in queue? Exchange
$q->extract();
$q->insert($entry, -$entry["score"]);
}
}
$q->setExtractFlags(SplPriorityQueue::EXTR_DATA);
return array_reverse(iterator_to_array($q));
}
以下是一些示例输入数据以及如何调用上述函数:
$input = [
["user" => "a", "score" => 17],
["user" => "b", "score" => 3],
["user" => "c", "score" => 10],
["user" => "d", "score" => 11],
["user" => "e", "score" => 5],
["user" => "f", "score" => 19],
["user" => "g", "score" => 7],
["user" => "h", "score" => 2],
["user" => "i", "score" => 18],
["user" => "j", "score" => 12],
["user" => "k", "score" => 10],
["user" => "l", "score" => 6],
["user" => "m", "score" => 9],
["user" => "n", "score" => 15],
];
$top = getTop($input, 5);
print_r($top);