1. 问题描述:
给定一个长度为 n 的整数数列,以及一个整数 k,请用快速选择算法求出数列从小到大排序后的第 k 个数。
输入格式
第一行包含两个整数 n 和 k。
第二行包含 n 个整数(所有整数均在 1∼10 ^ 9 范围内),表示整数数列。
输出格式
输出一个整数,表示数列的第 k 小数。
数据范围
1≤n≤100000,
1≤k≤n
输入样例:
5 3
2 4 1 5 3
输出样例:
3
来源:https://www.acwing.com/problem/content/description/788/
2. 思路分析:
分析题目可以知道我们需要在长度为n的数组中找到第k小的元素,在数组中找出第k小的元素可以使用快速选择算法,快速选择算法基于快速选择排序的思想(第k小的元素表示需要将元素从小到大进行调整),快速选择算法根据当前主元对应的位置与k的大小关系确定递归的位置,这样可以只递归一边,若当前主元的位置i大于等于k,说明答案应该是在i或者是i的左边,否则答案在i的右侧,可以参考力扣的215题,求解第k小与第k大的元素的方法都是一样的只是在比较的时候需要调整符号而已。
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:
# nums[j] >= t为大于等于而不是大于, 求解的是第k小的数字所以需要将小于当前主元的数字放到前面, 第k小下面的判断是大于等于第k大是小于等于所以只需要调整符号即可判断
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)
if __name__ == '__main__':
n, k = map(int, input().split())
nums = list(map(int, input().split()))
print(Solution().findKthLargest(nums, k))