786 第k个数(快速选择算法)

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))

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值