题目
给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。
请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
示例 1:
输入: [3,2,1,5,6,4] 和 k = 2
输出: 5
示例 2:
输入: [3,2,3,1,2,4,5,5,6] 和 k = 4
输出: 4
提示:
1 <= k <= nums.length <= 104
-104 <= nums[i] <= 104
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/kth-largest-element-in-an-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解答一
对于 PHP 来说这道题是非常简单的,因为 PHP 中大量这样的数组函数,可以很方便的对数组进行排序。这里我们只需要直接使用 sort()
函数就可以了。
class Solution {
/**
* @param Integer[] $nums
* @param Integer $k
* @return Integer
*/
function findKthLargest($nums, $k) {
rsort($nums);
return $nums[$k-1];
}
}
执行用时:24 ms, 在所有 PHP 提交中击败了49.48%的用户
内存消耗:19.5 MB, 在所有 PHP 提交中击败了83.51%的用户
通过测试用例:32 / 32
解答二
自己编写归并排序
class Solution {
/**
* @param Integer[] $nums
* @param Integer $k
* @return Integer
*/
function findKthLargest($nums, $k) {
$arr = $this->mergeSort($nums);
return $arr[$k-1];
}
/** 归并排序 */
function mergeSort($nums) {
$len = count($nums);
if ($len < 2) return $nums;
$m = intval($len / 2);
$left = $this->mergeSort(array_slice($nums, 0, $m));
$right = $this->mergeSort(array_slice($nums, $m, $len-$m));
$arr = [];
while (count($left) && count($right)) {
if ($left[0] >= $right[0])
$arr[] = array_shift($left);
else
$arr[] = array_shift($right);
}
while (count($left))
$arr[] = array_shift($left);
while (count($right))
$arr[] = array_shift($right);
return $arr;
}
}
执行用时:200 ms, 在所有 PHP 提交中击败了22.81%的用户
内存消耗:20.1 MB, 在所有 PHP 提交中击败了14.91%的用户
通过测试用例:32 / 32
解答三
自己编写快排
class Solution {
/**
* @param Integer[] $nums
* @param Integer $k
* @return Integer
*/
function findKthLargest($nums, $k) {
$this->quickSort($nums, 0, count($nums)-1);
return $nums[$k-1];
}
/** 快速排序 */
function quickSort(array &$nums, int $a, int $b) {
if ($a >= $b) return;
$i = $a;
$j = $b;
$mi = true;
while ($i < $j) {
if ($nums[$i] < $nums[$j]) {
[$nums[$i], $nums[$j]] = [$nums[$j], $nums[$i]];
$mi = !$mi;
}
$mi ? $j-- : $i++;
}
$this->quickSort($nums, $a, $i-1);
$this->quickSort($nums, $i+1, $b);
}
}
执行用时:824 ms, 在所有 PHP 提交中击败了16.67%的用户
内存消耗:21.8 MB, 在所有 PHP 提交中击败了11.40%的用户
通过测试用例:32 / 32
解答四 ✅
快排,但是只排 k 范围内的部分,并且在快排中选择中点数据时使用 rand()
函数,尽可能避免最坏的 O(n²)
情况出现。
class Solution {
/**
* @param Integer[] $nums
* @param Integer $k
* @return Integer
*/
function findKthLargest($nums, $k) {
return $this->quickSort($nums, 0, count($nums)-1, $k-1);
}
/** 快速排序 */
function quickSort(array &$nums, int $a, int $b, $k) {
if ($a >= $b) return $nums[$a];
$r = rand($a, $b);
[$nums[$a], $nums[$r]] = [$nums[$r], $nums[$a]];
$j = $a;
$v = $nums[$a];
for ($i = $a+1; $i <= $b; $i++) {
if ($nums[$i] > $v) {
$j++;
[$nums[$i], $nums[$j]] = [$nums[$j], $nums[$i]];
}
}
[$nums[$a], $nums[$j]] = [$nums[$j], $nums[$a]];
if ($k == $j) {
return $nums[$j];
} else if ($k < $j) {
return $this->quickSort($nums, $a, $j-1, $k);
} else {
return $this->quickSort($nums, $j+1, $b, $k);
}
}
}
执行用时:12 ms, 在所有 PHP 提交中击败了99.12%的用户
内存消耗:19.9 MB, 在所有 PHP 提交中击败了28.07%的用户
通过测试用例:32 / 32
解答五
采用堆排序,建立大根堆,依次取大根堆的根节点 k 次就可以了
class Solution {
/**
* @param Integer[] $nums
* @param Integer $k
* @return Integer
*/
function findKthLargest($nums, $k) {
$end = count($nums) - 1;
// 初始化大根堆
$this->initMaxHeap($nums, $end);
// 循环至取出 k
$max = null;
while ($k-- > 0) {
$max = $nums[0];
$nums[0] = $nums[$end];
$this->heapify($nums, --$end, 0);
}
return $max;
}
/** 初始化大根堆 */
function initMaxHeap(array &$nums, int $end) {
if ($end < 1) return;
for ($parent = intval(($end-1)/2); $parent >= 0; $parent--) {
$child = $parent * 2 + 1;
$child+1 <= $end and $nums[$child+1] > $nums[$child] and $child++;
if ($nums[$child] > $nums[$parent]) {
[$nums[$parent], $nums[$child]] = [$nums[$child], $nums[$parent]];
$this->heapify($nums, $end, $child);
}
}
}
/** 堆化整理分支 */
function heapify(array &$nums, int $end, int $parent) {
for (; $parent * 2 + 1 <= $end; $parent = $child) {
$child = $parent * 2 + 1;
$child+1 <= $end and $nums[$child+1] > $nums[$child] and $child++;
if ($nums[$child] <= $nums[$parent]) break;
[$nums[$parent], $nums[$child]] = [$nums[$child], $nums[$parent]];
}
}
}
执行用时:28 ms, 在所有 PHP 提交中击败了44.74%的用户
内存消耗:19.7 MB, 在所有 PHP 提交中击败了52.63%的用户
通过测试用例:32 / 32