5.查找最小的k 个元素
题目:输入n 个整数,输出其中最小的k 个。
题目:输入n 个整数,输出其中最小的k 个。
例如输入1,2,3,4,5,6,7 和8 这8 个数字,则最小的4 个数字为1,2,3 和4。
思路:维护一个k个元素的最大堆,初始元素取n个整数的前k个即可,遍历剩下的n-k个整数,取出每一个整数和最大堆的根节点也就是k个元素的最大值比较,若这个整数小于该根节点,说明根节点肯定不是最小的k个值里面的一个,直接用这个整数替换根节点并重新调整堆,这样堆里始终存储的是遍历到的整数里最小的k个,重复上述过程直到遍历结束,这样就获得了n个元素里面最小的k个。初始化堆的时间复杂度为O(klog(k))【更正,建堆过程的复杂度应该为O(k)】,后面替换根节点后重新调整需要的总的时间复杂度为O(k+nlog(k)),总的时间复杂度为O(nlog(k))。
C++ STL里面的set基于红黑树实现,在自定义set的排序函数为降序排列后,我们可以很方便的使用set来解决这个问题。
也可以自己实现堆处理。
这里给出两种实现的代码:
namespace MS100P_5
{
//采用STL的容器multiset
void findKleastNum(int data[], int length, int k, int result[])
{
multiset<int, greater<int>> dataHeap;
int i;
for (i = 0; i < k; i++)
dataHeap.insert(data[i]);
for (i = k; i < length; i++)
{
if (data[i] < *dataHeap.begin())
{
dataHeap.erase(dataHeap.begin());
dataHeap.insert(data[i]);
}
}
multiset<int>::iterator iter = dataHeap.begin();
for (i = 0; i < k; i++)
{
result[i] = *iter;
iter++;
}
}
//自己实现堆操作
//最大堆堆插入操作
void insert(int data[], int i) //data 待插入堆i,插入的位置 value 插入的值
{
int j,temp;
j = (i - 1) / 2;
temp = data[i];
while (j >= 0 && i != 0)
{
if (data[j] < temp)
data[i] = data[j];
else
break;
i = j;
j = (i-1) / 2;
}
data[i] = temp;
}
void insert2(int heap[], int i, int value)
{
//保险起见,可以增加i和数组大小的比较
for (; i>0 && heap[(i - 1) / 2]<value; i = (i - 1) / 2)
heap[i] = heap[(i - 1) / 2];
heap[i] = value;
}
void adjustHeap(int data[], int length, int i) //从i开始向下调整堆
{
int j, temp;
temp = data[i];
j = 2 * i + 1; //左孩子
while (j < length)
{
if ((j + 1 < length)&&data[j + 1] > data[j])
j++;
if (data[j]>temp) //又犯了低级错误,把temp写成了a[j],浪费时间呐
data[i] = data[j];
else
break;
i = j;
j = 2 * i + 1;
}
data[i] = temp;
}
void findKleastNum2(int data[], int length, int k, int result[])
{
int i;
for (i = 0; i < k; i++) //建立最大堆
{
insert2(result, i,data[i]);
}
for (i = k; i < length; i++)
{
if (data[i] < result[0])
{
result[0] = data[i];
adjustHeap(result, k, 0);
}
}
}
void test()
{
int data[20], result[5];
createArray(data, 20);
printArray(data,20);
findKleastNum(data,20,5,result);
printArray(result, 5);
findKleastNum2(data, 20, 5, result);
printArray(result, 5);
}
}