1. 问题描述:
在未排序的数组中找到第 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 ≤ 数组的长度。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/kth-largest-element-in-an-array
2. 思路分析:
分析题目可以知道我们可以使用快速选择算法找到第k小或者是第k大的元素,快速选择算法基于快速排序的基础,快速选择算法在递归的时候不是分别递归两边,我们可以根据k与一开始选择的数字x(主元)的位置i决定递归的是哪一边,如果k <= i说明可以递归i的左边包括i这个位置,否则递归右边,所以我们只需要在快速排序算法的基础上增加一个判断条件决定递归的是哪一边即可。对于快速排序算法我们记住代码模板即可这样在用到的时候直接写出来即可。我们可以调整循环中t(主元)与nums[i]或者nums[j]的关系来求解是第k大的元素还是第k小的元素,因为题目中问的是第k大的所以我们在求解的时候是需要逆序排序的,所以调整一下t与nums[i]和nums[j]的判断关系即可。
3. 代码如下:
from typing import List
class Solution:
def quickSort(self, nums: List[int], low: int, high: int, k: int):
if low >= high: return nums[low]
# 需要使用三个循环进行模拟
t = nums[low]
i, j = low, high
while i < j:
# 这里需要逆序相当于是快速排序中从大到小排序的过程, 注意是小于等于而不是小于因为我们是调整之后是由大到小排序的所以只有大于当前主元的元素移动到前面
while i < j and nums[j] <= t: j -= 1
if i < j:
nums[i] = nums[j]
i += 1
while i < j and nums[i] > t: i += 1
if i < j:
nums[j] = nums[i]
j -= 1
nums[i] = t
# 根据i与k的关系决定递归的是哪一边
if i >= k: return self.quickSort(nums, low, i, k)
return self.quickSort(nums, i + 1, high, k)
def findKthLargest(self, nums: List[int], k: int) -> int:
return self.quickSort(nums, 0, len(nums) - 1, k - 1)