剑指Offer——面试题30:最小的K个数

题目:输入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分别测试原始数组中是否有重复元素。

posted @ 2014-09-19 04:31  Superpig0501  阅读(271)  评论(0编辑  收藏  举报