zoukankan      html  css  js  c++  java
  • 快排解决寻找数组中的第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);
        }
    }

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

  • 相关阅读:
    webpack基础
    LeetCode232. 用栈实现队列做题笔记
    mysql 时间加减一个月
    leetcode 1381. 设计一个支持增量操作的栈 思路与算法
    LeetCode 141. 环形链表 做题笔记
    leetcode 707. 设计链表 做题笔记
    leetcode 876. 链表的中间结点 做题笔记
    leetcode 143. 重排链表 做题笔记
    leetcode 1365. 有多少小于当前数字的数字 做题笔记
    LeetCode1360. 日期之间隔几天 做题笔记
  • 原文地址:https://www.cnblogs.com/yweihum/p/13348251.html
Copyright © 2011-2022 走看看