【剑指offer】最小的K个数的几种解法

本文介绍了《剑指offer》中找到最小k个数的问题,提供了O(nlogk)的解决方案,包括使用最大堆、优先队列和红黑树,并对比了各种方法的实现细节和时间复杂度。此外,还提及了O(n)的快速排序划分思想算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:

输入n个整数,找出其中最小的k个数。例如输入4、5、1、6、2、7、3、8,则最小的4个数字是1、2、3、4。

常见思路:

这道题最简单的思路就是先把输入的n个整数排序,排序之后位于最前面的k个数就是最小的k个数。常见的排序算法都可以使用,时间复杂度就是排序的时间复杂度,较好的时间复杂度为O(nlogn)O(nlogn)O(nlogn),这里顺便提一下python中的内置sort函数,使用的是蒂姆排序,结合了归并排序和插入排序,最坏的时间复杂度为O(nlogn)O(nlogn)O(nlogn)
下面介绍几种时间复杂度小于O(nlogn)O(nlogn)O(nlogn)的算法。

1.O(nlogk)O(nlogk)O(nlogk)的算法:

这种思想主要就是维护一个大小为k的数据容器;首先创建一个大小为k的数据容器来存储最小的k个数字,接下来我们每次从输入的n个整数中读取一个数,比较待插入的整数和容器中的最大值,如果比已有的最大值小,就插入容器替换这个最大值;否则就不进行操作,因为这个数比容器的最大值还要大。
我们需要对容器做的操作有:

  1. 在k个整数中找到最大数。
  2. 在容器中删除最大值。
  3. 插入一个新的数字。

如果用一个二叉树来实现这个数据容器,那么我们可以在O(logk)O(logk)O(logk)时间内实现这三个步骤。因此对于n个输入数字而言,总的时间效率就是O(nlogk)O(nlogk)O(nlogk),这种思路特别适合处理海量数据。

这个数据容器有多种实现方式,下面介绍主要的几种实现方式。

1.1 最大堆:

我们可以选择不同的二叉树来实现这个数据容器。在最大堆中,根结点的值总是大于它的子树中任意结点的值。于是我们可以在O(1)O(1)O(1)时间得到已有的k个数字中的最大值,但需要O(logk)O(logk)O(logk)时间完成删除及插入操作。
下面是实现的代码:通过数组模拟最大堆。

class Solution {
   
   
public:
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
   
   
        vector<int> res;
        if(input.empty() || input.size() < k || k <= 0) return res;
        for(int i = 0; i < k; ++i){
   
   
            res.push_back(input[i]);
        }
        for(int i = k/2-1; i >= 0; i--){
   
    // 初始化堆
            adjustHeap(res, i, k);
        }
        for(int i = k; i < input.size(); i++){
   
   
            if(input[i] < res[0]){
   
      // 存在更小的数字时
                res[0] = input[i];
                adjustHeap(res, 0, k)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值