面试题40. 最小的k个数
输入整数数组 arr ,找出其中最小的 k 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。
示例 1:
输入:arr = [3,2,1], k = 2
输出:[1,2] 或者 [2,1]
示例 2:
输入:arr = [0,1,2,1], k = 1
输出:[0]
限制:
0 <= k <= arr.length <= 10000
0 <= arr[i] <= 10000
思路一:排序法
class Solution {
public:
vector<int> getLeastNumbers(vector<int>& arr, int k) {
if (k <= 0 || k > nums.size()){
return {};
}
sort(arr.begin(), arr.end());
return vector<int>(arr.begin(), arr.begin() + k);
/*
vector ans;
for (int i=0; i
}
};
/*48ms,21.1MB*/
/*64ms,21.7MB*/
时间复杂度:O(nlogn)
空间复杂度:O(1)
思路二:multiset最大堆
class Solution {
public:
vector<int> getLeastNumbers(vector<int>& arr, int k) {
int len = arr.size();
if (k <= 0 || k > len){
return {};
}
//显式指定最大堆,default is less
multiset<int, greater<int>> set;
for (int i=0; i<len; i++){
if (set.size() < k){
set.insert(arr[i]);
} else {
if (arr[i] < *set.begin()){
set.erase(set.begin());
set.insert(arr[i]);
}
}
}
return vector<int>(set.begin(), set.end());
}
};
/*44ms,26.4MB*/
时间复杂度:O(n)
空间复杂度:O(k)
参考链接:
https://leetcode-cn.com/problems/zui-xiao-de-kge-shu-lcof/solution/mian-shi-ti-40-san-chong-jie-fa-pai-xu-multisetzui/
思路:堆
class Solution {
public:
vector<int> getLeastNumbers(vector<int>& arr, int k) {
if (0 == k) return {};
priority_queue<int> q;
for (int i=0; i<k; i++) q.push(arr[i]);
for (int i=k; i<arr.size(); i++) {
if (arr[i] < q.top()) {
q.pop();
q.push(arr[i]);
}
}
vector<int> ans(k, 0);
for (int i=k-1; i>=0; i--) {
ans[i] = q.top();
q.pop();
}
return ans;
}
};
/*76ms,21.1MB*/
时间复杂度:O(nlogk)
空间复杂度:O(k)
思路:快排
假设划分函数返回的下标是 pos(表示分界值 basic 最终在数组中的位置),即 basic 是数组中第 pos - l + 1 小的数,那么一共会有三种情况:
class Solution {
public:
vector<int> getLeastNumbers(vector<int>& arr, int k) {
qSort(arr, 0, arr.size()-1, k);
//vector ans(k, 0);
//for (int i=0; i
//return ans;
return vector<int>(arr.begin(), arr.begin() + k);
}
void qSort(vector<int>& arr, int l, int r, int k) {
if (l >= r) return;
int pos = partition(arr, l, r);
int num = pos - l + 1;
if (num == k) return;
else if (num > k) qSort(arr, l, pos-1, k);
else qSort(arr, pos+1, r, k-num);
}
int partition(vector<int>& arr, int l, int r) {
int idx = rand() % (r - l + 1) + l;
swap(arr[idx], arr[r]);
int basic = arr[r];
int left = l, right = r;
while (left < right) {
while (left < right && arr[left] <= basic) left++;
while (left < right && arr[right] >= basic) right--;
if (left < right) swap(arr[left], arr[right]);
}
arr[r] = arr[left];
arr[left] = basic;
return left;
}
};
/*40ms,20.1MB*/
时间复杂度:平均复杂度O(n),最坏时间复杂度为O(n*n)
空间复杂度:O(logn)