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

问题描述

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

解题报告

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

猜你喜欢

转载自blog.csdn.net/qq_27690765/article/details/104986960
今日推荐