Title

在未排序的数组中找到第 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 ≤ 数组的长度。

基于快速排序的选择方法

Solve

先对原数组排序,再返回倒数第k个位置,这样平均时间复杂度是O(nlogn)。

我们来回顾一下快速排序,对数组array[l…r]的快速排序过程是:

分解:将数组array[l…r]划分成两个子数组array[l…q-1]、array[q+1…r],使得a[l…q-1]中的每个元素小于等于a[q],且a[q]小于等于a[q+1…r]中的每个元素。
解决:通过递归调用快速排序,对子数组array[l…q-1]、array[q+1…r]进行排序。
合并:因为子数组都是原址排序,所以不需要进行合并操作,a[l…r]已经有序。

由此可以发现每次经过划分操作后,一定可以确定一个元素的最终位置,即x的最终位置为q,并且保证a[l…q-1]中的每个元素小于等于a[q],且a[q]小于等于array[q+1…r]中的每个元素。

所以只要某次划分的q为倒数第k个下标的时候,就已经找到了答案,我们只关心这一点,至于array[l…q-1]、array[q+1…r]是否是有序的无需关心。

因此我们可以改进快速排序算法来解决这个问题:在分解的过程当中,我们会对子数组进行划分,如果划分得到的 q 正好就是我们需要的下标,就直接返回 a[q];否则,如果 q 比目标下标小,就递归右子区间,否则递归左子区间。

这样就可以把原来递归两个区间变成只递归一个区间,提高了时间效率。这就是「快速选择」算法。

我们知道快速排序的性能和「划分」出的子数组的长度密切相关。直观地理解如果每次规模为 n 的问题我们都划分成 1 和 n - 1,每次递归的时候又向 n - 1 的集合中递归,这种情况是最坏的,时间代价是 O(n 2)。

我们可以引入随机化来加速这个过程,它的时间代价的期望是 O(n),证明过程可以参考「《算法导论》9.2:期望为线性的选择算法」。

Code

 def findKthLargest_QuickSelection(self, nums: List[int], k: int) -> int:def quickSelect(a: List[int], l: int, r: int, k: int):q = randomPartition(a, l, r)return a[q] if q == k else quickSelect(a, q + 1, r, k) if q < k else quickSelect(a, l, q - 1, k)def partition(a: List[int], l: int, r: int):x, i = a[r], l - 1for j in range(l, r):if a[j] <= x:i += 1a[i], a[j] = a[j], a[i]a[i + 1], a[r] = a[r], a[i + 1]return i + 1def randomPartition(a: List[int], l: int, r: int):i = random.randint(l, r)a[i], a[r] = a[r], a[i]return partition(a, l, r)return quickSelect(nums, 0, len(nums) - 1, len(nums) - k)

复杂度分析

时间复杂度:O(n),如上文所述,证明过程可以参考「《算法导论》9.2:期望为线性的选择算法」。

空间复杂度:O(logn),递归使用栈空间的空间代价的期望为 O(logn)。

基于堆排序的选择方法

Solve

可以建立一个小根堆,做k-1次删除操作后堆顶元素就是我们要找的答案。

在很多语言中,都有优先队列或堆的容器可以直接使用,但在面试中,面试官更倾向于让面试者自己实现一个堆,搞懂「建堆」、「调整」和「删除」的过程。

取nums前k个元素建立大小为k的最小堆,剩余k+1到N个元素依次和堆顶比较,如果比堆顶大,则替换当前堆顶,并维护最小堆,最终最小堆里是前k大的元素,堆顶为前k大的元素中最小的元素。

Code

 def findKthLargest_MinimumHeap(self, nums: List[int], k: int) -> int:def shift(i, k):flag = 0while (i * 2 + 1) < k and flag == 0:t = iif nums[i] > nums[2 * i + 1]:t = 2 * i + 1if (i * 2 + 2) < k and nums[t] > nums[2 * i + 2]:t = 2 * i + 2if t == i:flag = 1else:nums[i], nums[t] = nums[t], nums[i]i = tfor i in range(k // 2, -1, -1):shift(i, k)for i in range(k, len(nums)):if nums[0] < nums[i]:nums[0] = nums[i]shift(0, k)return nums[0]

复杂度分析

时间复杂度:O(nlogn),建堆的时间代价是 O(n),删除的总代价是 O(klogn),因为 k<n,故渐进时间复杂为 O(n+klogn)=O(nlogn)。
空间复杂度:O(logn),即递归使用栈空间的空间代价。

215. Kth Largest Element in an Array 数组中的第K个最大元素相关推荐

  1. 网易2016 实习研发工程师 [编程题]寻找第K大 and leetcode 215. Kth Largest Element in an Array...

    传送门 有一个整数数组,请你根据快速排序的思路,找出数组中第K大的数. 给定一个整数数组a,同时给定它的大小n和要找的K(K在1到n之间),请返回第K大的数,保证答案存在. 测试样例: [1,3,5, ...

  2. 剑指offer 最小的k个数 leetcode 215. Kth Largest Element in an Array

    注意multiset的一个bug: multiset带一个参数的erase函数原型有两种.一是传递一个元素值,如上面例子代码中,这时候删除的是集合中所有值等于输入值的元素,并且返回删除的元素个数:另外 ...

  3. [leedcode 215] Kth Largest Element in an Array

    Find the kth largest element in an unsorted array. Note that it is the kth largest element in the so ...

  4. [swift] LeetCode 215. Kth Largest Element in an Array

    Find the kth largest element in an unsorted array. Note that it is the kth largest element in the so ...

  5. LeetCode 215 Kth Largest Element in an Array

    思路: 跟找第kth小的数相反,数组逆向排序.从前找第k - 1个数. 1 public class Solution { 2 public int findKthLargest(int[] arra ...

  6. leetcode 215. Kth Largest Element in an Array | 215. 数组中的第K个最大元素(Java)

    题目 https://leetcode.com/problems/kth-largest-element-in-an-array/ 题解 本题需要建立大顶堆.关于堆的数据结构,需要知道: 堆 什么是堆 ...

  7. vector删除第i个元素_LeetCode每日一题 Q215数组中的第K个最大元素

    Question 215: Kth Largest Element in an Array Difficulty: Medium 题目描述 在未排序的数组中找到第 k 个最大的元素.请注意,你需要找的 ...

  8. 力扣215:数组中的第K个最大元素 (leetcode 215:Kth Largest Element In An Array)

    题目链接:https://leetcode.cn/problems/kth-largest-element-in-an-array 目录: 一.题目描述 1.中文 2.英文 二.解决方法 1.直接排序 ...

  9. LeetCode 215. Kth Largest Element in an Array--数字第K大的元素--最大堆或优先队列--C++,Python解法

    题目地址:Kth Largest Element in an Array - LeetCode Find the kth largest element in an unsorted array. N ...

最新文章

  1. Ubuntu下如何解压缩zip,tar,tar.gz,tar.bz2文件
  2. 做算法题时的一些小技巧
  3. VTK:Filtering之ContoursFromPolyData
  4. iOS : 静态库(.framework)合并
  5. 一图解惑SQL JOINS
  6. java array 元素的位置_介绍java中的两种排序工具Arrays和Collections
  7. vite+vue3 整合vue-router4和vuex4
  8. UE4【C++】子弹伤害系统使用
  9. 计算机三级-数据库技术
  10. Echarts官方文档!
  11. jwplayer播放器
  12. 手机触屏事件(jquery)
  13. python版本和Matlab版本对应的关系,python调用matlab
  14. 安装SQL2008时遇到未能加载文件或file:///d:microsoft..sql.chainer.packagedata.dll或它的某个依赖项
  15. 红杉观点|生成式AI:一个创造性的新世界
  16. yun yun de
  17. 工程师如何在面试中脱颖而出
  18. Android 开发飞机大战
  19. 中广互联就TVOS对王效杰司长的采访报道
  20. 全速USB和高速USB的识别过程分析

热门文章

  1. 【网络流】【待补】C. Heidi and Library (hard)
  2. HBase学习笔记2 - HBase shell常用命令
  3. 大型网站系统架构实践(五)深入探讨web应用高可用方案
  4. [leetcode]Edit Distance
  5. 网页客户端调用gSoap发布服务,以及中文乱码问题
  6. linux 修改默认路径吗,linux中vsftp修改默认路径
  7. mysql 经典优化案例_MySQL-SQL优化10大最经典案例详解
  8. mysql 导入sql脚本_mysql 导入 sql文件
  9. java for each 的源_Java JDK1.5的新特性之for-each循环的底层原理
  10. 三态门三个状态vhdl_人防门是什么?为什么会侵线导致重庆地铁事故