40.最小的K个数

40.最小的K个数

1.题目的描述

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

2.方法1(最大堆)

最大堆实现,当堆小于K时,依次插入数字,当堆大于K时,待插入的数字与堆顶比较,如果小于则插入,否则不插入。

3.代码

class Solution {
public:
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
        vector<int> result;
        if(input.empty() || k <= 0 || k>input.size())
            return result;
        multiset<int,greater<int>> setData;
        
        
        for(int i =0;i < input.size();++i){
            if(setData.size() < k){
                setData.insert(input[i]);
            }
            else{
                multiset<int,greater<int>>::iterator max = setData.begin();
                if(input[i] < *max){
                    setData.erase(max);
                    setData.insert(input[i]);
                }
            }
        }
        for(multiset<int,greater<int>>::iterator iter = setData.begin();iter != setData.end();++iter){
            result.push_back(*iter);
        }
        return result;
    }
};

4.复杂度分析

时间复杂度:O(N*logK)
空间复杂度:O(1)

5.方法2(partition)

采用快排的思想,通过partition把数组元素放到正确的位置index,如果index > k - 1,即index左边的数(都小于右边)大于k个,因此right = index - 1;如果index < k - 1,说明index左边的数(都小于右边)小于k个,因此left = index + 1;如果index == k - 1,说明找到了k个最小的数。最后把数组的前k个数放入结果数组。

6.代码

class Solution {
public:
    vector<int> getLeastNumbers(vector<int>& arr, int k) {
        vector<int> res;
        if(arr.empty() || k <= 0 || k > arr.size()){
            return res;
        }
        int left = 0;
        int right = arr.size() - 1;
        int index = 0;

        while(index != k - 1){
            index = partition(arr, left, right);
            if(index > k - 1){
                right = index - 1;
            }
            else{
                left = index + 1;
            }
        }
        for(int i = 0;i < k;++i){
            res.push_back(arr[i]);
        }
        return res;
    }
    int partition(vector<int>& arr, int left, int right){
        int t = left;
        for(int i = left;i < right; ++i){
            if(arr[i] < arr[right]){
                swap(arr[t++], arr[i]);
            }
        }
        swap(arr[t], arr[right]);

        return t;
    }
};

7.复杂度分析

时间复杂度:O(N),partition操作的时间复杂度是O(N),每次执行的时间复杂度都比上一次小,加起来就是O(N)。
空间复杂度:O(1)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值