题目:输入N个数字,找出其中最小的K个数。
思路:维护一个数组KMin,长度为K,存放最小的K个数。遍历原始数组的过程中,如果KMin不满,就直接在后边插入新的数字;如果KMin满了,就要找到其中最大的数字,和当前遍历原始数组时遇到的数字进行比较,决定是否更新。由于每次都要获得KMin中最大的数字,所以可以把KMin用一个大顶堆来实现,当KMin满了的时候,就建堆,之后在每次遍历时,都用当前遍历得到的元素与KMin的堆顶比较,决定是否更新,如果更新,就维护堆。其中建堆过程和维护堆的过程共用一个函数AdjustHeap来描述。算法用C/C++实现。
void AdjustHeap(int* const arr, const int length){
for(int i = length / 2 - 1; i >= 0; i--){
int temp = arr[i];
int k = 0;
for(int j = i * 2 + 1; j < length; j = k * 2 + 1){
k = j;
if(j + 1 < length)
k = arr[j] > arr[j + 1] ? j : j + 1;
if(arr[k] > arr[i]){
arr[(j - 1) / 2] = arr[k];
arr[k] = temp;
}
else
break;
}
}
}
int* GetKMin(int* const arr, const int length, const int K){
if(K <= 0) return NULL;
int* KMin = new int[K];
for(int i = 0; i < length; i++){
if(i <= K)
KMin[i] = arr[i];
if(i == K)
AdjustHeap(KMin, K);
if(i > K)
if(arr[i] < KMin[0]){
KMin[0] = arr[i];
AdjustHeap(KMin, K);
}
}
return KMin;
}
测试代码:
int main(){
const int K = 5;
const int B = 10;
static int TestBase[B] = {6, 2, 20, 13, 9, 11, 7, 5, 1, 8};
static int TestBase2[B] = {6, 2, 20, 13, 9, 11, 7, 5, 1, 6};
int i = 0;
for(i = 0; i < B; i++) cout << TestBase[i] << " ";
cout << endl;
int * KMin = GetKMin(TestBase, B, K);
if(KMin)
for(i = 0; i < K && i < B; i++) cout << KMin[i] << " ";
cout << endl;
return 0;
}
测试用例:
K = 5, B = 10;
K = 1, B = 10;
K = 0, B = 10;
K = -1, B = 10;
K = 15, B = 10;
还可以使用TestBase和TestBase2分别测试原始数组中是否有重复元素。