题目:输入n个整数,找出其中最小的k个数。例如:输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。
1.利用简单排序找到前k个数
void simpleSearchLeastNumbers(unsigned int* array, int length, unsigned int* result,
int k) {
if (NULL == array || 0 >= length || k > length || NULL == result
|| 0 >= k) {
return;
}
int minItemPosition = 0;
for (int i = 0; i < k; ++i) {
minItemPosition = i;
for (int j = i + 1; j < length; ++j) {
if (array[minItemPosition] > array[j]) {
minItemPosition = j;
}
}
std::swap(array[minItemPosition], array[i]);
result[i] = array[i];
}
return;
}
2.利用快速排序中的划分函数parition找到第k小(或大)的数的位置,则前k个数就是要寻找的数
//用快速排序中的partition函数找到枢轴的位置
int partition(unsigned int* array, int length, int start, int end) {
if (NULL == array || 0 >= length || 0 > start || start > end) {
return -1;
}
int j = start - 1;
for (int i = start; i < end; ++i) {
if (array[i] < array[end]) {
std::swap(array[++j], array[i]);
}
}
std::swap(array[++j], array[end]);
return j;
}
void getLeastNumbers(unsigned int* array, int length, unsigned int* result,
int k) {
if (NULL == array || 0 >= length || k > length || NULL == result
|| 0 >= k) {
return;
}
int start = 0, end = length - 1;
int index = partition(array, length, start, end);
while (index != k - 1) {
if (index < k - 1) {
start = index + 1;
} else {
end = index - 1;
}
index = partition(array, length, start, end);
}
for (int i = 0; i < k; ++i) {
result[i] = array[i];
}
return;
}
3.第二种思路的递归式解法
void findLeastNumbers(int* array, unsigned int start, unsigned int end,
unsigned int k) {
if (NULL == array || start < 0 || start > end || 0 == k) {
return;
}
if (start < end) {
unsigned int povitValue = partition(array, start, end);
if (povitValue + 1 == k) {
return;
}
findLatestKItem(array, start, povitValue - 1, k);
findLatestKItem(array, povitValue + 1, end, k);
}
}
4.利用最大(或最小)堆求解,具体过程:先将前k个数建立最大(小)堆,将后序各个元素分别与堆顶比较,如果其小于(大于)堆顶,则将此元素作为新堆顶元素并重新建堆。
//在某个结点上建立大顶堆
void maxHeapify(unsigned int* array, int length, int parent) {
int largest = parent;
int left = 2 * parent, right = 2 * parent + 1;
if (left <= length && array[left] > array[parent]) {
largest = left;
}
if (right <= length && array[right] > array[largest]) {
largest = right;
}
if (largest != parent) {
std::swap(array[parent], array[largest]);
maxHeapify(array, length, largest);
}
}
//构建大顶堆--从数组的长度的length/2处开始建堆
void buildMaxHeap(unsigned int* array, int length) {
for (int i = length / 2; i > 0; --i) {
maxHeapify(array, length, i);
}
}
//利用前k个元素建立一个最大堆,从k+1元素开始于堆顶比较如果其小于堆顶,则将其把堆顶覆盖,重复操作后序元素直至最后一个元素
void getLeastNumbersWithMaxHeap(unsigned int *array, int length,
unsigned int* result, int k) {
if (NULL == array || 0 >= length || k > length || NULL == result
|| 0 >= k) {
return;
}
//申请建堆的空间
unsigned int* x = new unsigned int[k + 1];
for (int i = 0; i < k; ++i) {
x[i + 1] = array[i];
}
buildMaxHeap(x, k);
for (int i = k; i < length; ++i) {
if (array[i] < x[1]) {
x[1] = array[i];
maxHeapify(x, length, 1);
}
}
//将结果copy到result
for (int i = 1; i <= k; ++i) {
result[i - 1] = x[i];
}
delete x;
return;
}
测试代码
/*
*
* Created on: 2014-4-4 23:36:35
* Author: danDingCongRong
*
*/
#include<iostream>
using namespace std;
//输入各个数组元素
void inputArray(unsigned int* array, int length) {
for (int i = 0; i < length; ++i) {
cin >> array[i];
}
}
//初始化数组中的各个元素为指定值
void initArray(unsigned int* array, int length, int value) {
for (int i = 0; i < length; ++i) {
array[i] = value;
}
}
//打印输出数组中的各个元素
void outputArray(unsigned int* array, int length) {
for (int i = 0; i < length - 1; ++i) {
cout << array[i] << '\t';
}
cout << array[length - 1] << endl;
}
int main() {
int k = 0, length = 0;
cout << "寻找数组中最小的k个数." << endl;
cout << "请输入数组的长度及k的值:" << endl;
while (cin >> length >> k) {
unsigned int* x = new unsigned int[length];
unsigned int* result = new unsigned int[k];
inputArray(x, length);
initArray(x, k, 0);
simpleSearchLeastNumbers(x, length, result, k);
outputArray(result, k);
initArray(x, k, 0);
getLeastNumbersWithPartition(x, length, result, k);
outputArray(result, k);
initArray(x, k, 0);
getLeastNumbers(x, length, result, k);
outputArray(result, k);
initArray(x, k, 0);
findLeastNumbers(x, 0, length - 1, k);
outputArray(x, k);
initArray(result, k, 0);
getLeastNumbersWithMaxHeap(x, length, result, k);
outputArray(result, k);
delete result;
cout << "请输入数组的长度:" << endl;
}
return 0;
注:部分算法参考自编程之美与剑指offer