问题描述
输入整数数组
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(n⋅logk),维护大小为k的堆,复杂度为 O ( l o g k ) O(logk) O(logk),最坏情况下数组里的 n n n 个数都会插入,所以时间复杂度一共是 O ( n ⋅ l o g k ) O(n\cdot logk) O(n⋅logk)
空 间 复 杂 度 空间复杂度 空间复杂度: 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;
}
};