输入整数数组 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]
这是一道非常经典的题目,有三种做法:
1、直接sort排序取前K大
2、堆排序
3、快排思想
第一种解法太无聊不说了
堆就是根节点大于孩子结点,兄弟结点不区分大小关系的一种数据结构。
#include
using namespace std;
const int MAXN = 10000;
int n;
int heap[MAXN];
inline int& getRef(int root) {
return heap[root-1];
}
void push(int v) {
heap[n++] = v;
int pos = n, nextPos = pos>>1;
while(pos > 1 && getRef(pos) > getRef(nextPos) )
{
swap(getRef(pos), getRef(nextPos));
pos = nextPos, nextPos >>= 1;
}
}
int pop()
{
swap(getRef(1), getRef(n));
int res = heap[--n];
for(int root = 1; ; ) {
int left = root<<1;
int right = root<<1|1;
if(right <= n && getRef(root) < max(getRef(left), getRef(right))) {
if(getRef(left) > getRef(right)) {
swap(getRef(left), getRef(root));
root = left;
} else {
swap(getRef(right), getRef(root));
root = right;
}
} else if (left <= n && getRef(root) < getRef(left)) {
swap(getRef(left), getRef(root));
root = left;
break;
} else {
break;
}
}
return res;
}
vector<int> getLeastNumbers(vector<int>& arr, int k)
{
for(int i=0; i<arr.size(); i++){
push(arr[i]);
if(n>k)
pop();
}
return vector<int>(heap, heap+k);
}
int main()
{
vector<int> arr;
arr.push_back(1);
arr.push_back(2);
arr.push_back(3);
int k = 2;
getLeastNumbers(arr, k);
}
class Solution {
public:
vector<int> ans;
int ansCnt;
void quickSort(vector<int>& arr, int left, int right, int k) {
if(left>right) return;
if(ansCnt == k) return ;
int flag = arr[left];
int i = left, j = right;
while(i<j)
{
while(arr[j]>=flag && i<j) j--;
arr[i] = arr[j];
while(arr[i]<=flag && i<j) i++;
arr[j] = arr[i];
}
arr[i] = flag;
if(i<k){
for(int t=left; t<=i; t++){
ans.push_back(arr[t]);
ansCnt++;
}
if(ansCnt == k)
return;
quickSort(arr, i+1, right, k);
}
if(i>=k)
quickSort(arr, left, i-1, k);
}
vector<int> getLeastNumbers(vector<int>& arr, int k)
{
int l = 0;
int r = arr.size()-1;
quickSort(arr, 0, r, k);
return ans;
}
};