快排解决寻找数组中的第K个最大元素

Posted 大眼小眼

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了快排解决寻找数组中的第K个最大元素相关的知识,希望对你有一定的参考价值。

 

题目:数组中的第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
说明:

你可以假设 k 总是有效的,且 1 ≤ k ≤ 数组的长度。
链接:https://leetcode-cn.com/problems/kth-largest-element-in-an-array

这是一个来自 leetcode 的题目,有很多的解决方式,属于排序类的问题。排序类的算法大致就这些几种 排序算法,可以解决这个问题的比如冒泡排序、堆排序、快排等。最近有参与了几场面试,快排的伪代码也大概写了  3  次了,这次决定要使用快排解决这个问题。

class Solution {
    private $k_size;
    private $count = 0;
    /**
     * @param Integer[] $nums
     * @param Integer $k
     * @return Integer
     */
    function findKthLargest($nums, $k) {
        $right = sizeof($nums);
        $this->quickSort($nums, 0, $right-1);
        return $nums[$right-$k];
    }

    function quickSort(&$data, $start, $end) {
        if($start >= $end)
            return;
        $i = $start;
        $j = $end;
        $key = $data[$i]; //快排的枢纽元素,这里只简单取了第一个元素作为枢纽元,快排的效率可能很受影响
        while($i<$j) {
            while($i<$j && $data[$j] > $key)
                $j--;
            while($i<$j && $data[$i] <= $key)
                $i++;
            if ($j != $i)
                list($data[$i], $data[$j]) = array($data[$j], $data[$i]);
        }
        list($data[$start], $data[$j]) = array($data[$j], $data[$start]); //快排最后的操作,以枢纽元为分割点,左边的元素小于枢纽元,右边的元素大于枢纽元
        $this->quickSort($data,0,$i-1);
        $this->quickSort($data,$i+1,$end);
    }
}

上面使用了比较简洁、易懂的 php 代码,使用快排的思想对元素进行排序。我提交了代码,但是最后一个测试用例没有通过,所以考虑优化的方向。

很显然既然是找第 K 个最大元素,小于 K 的数据我就没有必要对他们就行快排,所以在后面两行加上一个条件可以避免很多没必要的操作。代码我就不贴了,贴一个我看的不太懂的一个。

class Solution {
    private $k_size;
    private $count = 0;
    /**
     * @param Integer[] $nums
     * @param Integer $k
     * @return Integer
     */
    function findKthLargest($nums, $k) {
        $this->k_size = $k;
        return $this->quickSort($nums, 0, count($nums)-1);
    }

    function quickSort(&$nums, $q, $r) {
        if($q >= $r) return $nums[$q];
        $i = $j = $q;

        //生成随机数(枢纽元选取,快排更稳定)
        $mtrand = mt_rand($q, $r);
        $tmp = $nums[$mtrand];
        $nums[$mtrand] = $nums[$r];
        $nums[$r] = $tmp;

        while($j<$r){
            if($nums[$j]>$nums[$r]){
                list($nums[$i],$nums[$j]) = [$nums[$j],$nums[$i]];
                ++$i;
            }
            ++$j;
        }

        list($nums[$i],$nums[$j]) = [$nums[$j],$nums[$i]];

        if($i+1 == $this->k_size) return $nums[$i];
        if($i+1>$this->k_size) return $this->quickSort($nums, $q, $i-1);
        return $this->quickSort($nums, $i+1, $r);
    }
}

 

参考《数据结构与算法分析》 第七章 《排序》

以上是关于快排解决寻找数组中的第K个最大元素的主要内容,如果未能解决你的问题,请参考以下文章

快排查找数组中的第K个最大元素

Leetcode215. 数组中的第K个最大元素(快排)

Leetcode——数组中的第K个最大元素

c++ 快排思想查找第k小数……注意是小

数组中的第K个最大元素

数组中的第K个最大元素