Leetcode 面试题40. 最小的k个数【最大堆&快排】

1 篇文章 0 订阅
1 篇文章 0 订阅

问题描述

输入整数数组 a r r arr arr,找出其中最小的 k k k 个数。
输 入 输入
arr = [3,2,1], k = 2
输 出 输出 :[1,2] 或者 [2,1]

解题报告

  • 方法一:堆
    维护大小为k的堆,当遍历完数组时,输出堆中的元素。
    时 间 复 杂 度 时间复杂度 O ( n ⋅ l o g k ) O(n\cdot log k) O(nlogk),维护大小为k的堆,复杂度为 O ( l o g k ) O(logk) O(logk),最坏情况下数组里的 n n n 个数都会插入,所以时间复杂度一共是 O ( n ⋅ l o g k ) O(n\cdot logk) O(nlogk)
    空 间 复 杂 度 空间复杂度 O ( k ) O(k) O(k)
  • 方法二:快速排序
    借助基准线,一次划分之后,只需要处理其中一边的元素。
    时 间 复 杂 度 时间复杂度 :最好的情况: O ( k ) O(k) O(k),最坏的情况: O ( n k ) O(nk) O(nk),每次的划分点都是最大值或最小值,一共需要划分 k k k次,而一次划分需要线性的时间复杂度。
    空 间 复 杂 度 空间复杂度 O ( l o g n ) O(logn) O(logn)

实现代码

class Solution {
public:
    vector<int> getLeastNumbers(vector<int>& arr, int k) {
        priority_queue<int>pq;
        vector<int>ans(k);
        if(k==0) return ans;
        for(int i=0;i<k;i++){
            pq.push(arr[i]);
        }
        for(int i=k;i<arr.size();i++){
            if(pq.top()>arr[i]){
                pq.pop();
                pq.push(arr[i]);
            }
        }
        for(int i=0;i<k;i++){
            ans[i]=pq.top();
            pq.pop();
        }
        return ans;
    }
};
  • 快速排序
class Solution {
public:
    vector<int> getLeastNumbers(vector<int>& arr, int k) {
        int n=arr.size();
        if(n==k) return arr;
        if(n<k || k<=0 || n==0) return vector<int>();
        int l=0,r=n-1;
        int index=partition(arr,l,r);
        while(index!=k-1){
            if(index>k-1) r=index-1;
            else l=index+1;
            index=partition(arr,l,r);
        }
        return vector<int>(arr.begin(),arr.begin()+k);
    }
    int partition(vector<int>&arr,int l,int r){
        int temp=arr[l];
        while(l<r){
            while(l<r && arr[r]>=temp) r--;
            arr[l]=arr[r];
            while(l<r && arr[l]<=temp) l++;
            arr[r]=arr[l]; 
        } 
        arr[l]=temp;
        return l;
    }
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值