刷题笔记 | C++ | LeetCode最小的k个数

题目描述:链接

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

示例
输入:arr = [3,2,1], k = 2
输出:[1,2] 或者 [2,1]

解题思想:参考链接
  1. 全局排序,O(n*lg(n))
  2. 局部排序,只排序TopK个数,O(n*k)
  3. 堆,TopK个数也不排序了,O(n*lg(k))
  4. 分治法,每个分支“都要”递归,例如:快速排序,O(n*lg(n))
  5. 减治法,“只要”递归一个分支,例如:二分查找O(lg(n)),随机选择O(n)
    TopK的另一个解法:随机选择+partition

本文采用堆,来维护一个长度为k的大根堆,其最顶端为这个堆里面最大的数

  • 首先取输入数组nums[0…k-1],也就是数组的前k个数来构建大根堆top[0…k],则top[0]是大根堆的顶端,数值最大
  • 然后对于nums[k…n],即数组后面的数进行遍历,如果当前数> top[0],则将top[0] = 当前数 并且 重新将数组top调整为大根堆。
  • 最终遍历完成后,数组top[0…k]中保存的为数组最小的k个数并返回。
C++实现代码:
class Solution {
private:
    void HeapAjust(vector<int>& nums, int parent, int len){
        int tmp = nums[parent];
        int child = 2*parent+1;
        
        while(child < len){
            if(child + 1 < len && nums[child] < nums[child + 1] ){
                child++;
            }
            if(nums[child] < tmp){
                break;
            }
            nums[parent] = nums[child];
            parent = child;
            child = 2*parent+1;
        }
        nums[parent] = tmp;
    }
public:
    vector<int> getLeastNumbers(vector<int>& arr, int k) {
        
        int l = arr.size();
        
        if(k < 1 || l < 1) return vector<int>();
        
        vector<int> topk(arr.begin(), arr.begin()+k);
        for(int i = k / 2 - 1; i >=0; i--){
            HeapAjust(topk, i, k);
        }
        for(int i = k; i < l; i++){
            if(topk[0] > arr[i]){
                topk[0] = arr[i];
                HeapAjust(topk, 0, k);
            }
        }
        return topk;
    }
};

参考链接:
排序算法 | 堆排序
c++基础之vector、数组初始化

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值