面试中经常会遇到查找最大的K个元素或者最小的K个元素的问题。如果是查找最大的K个元素,就用小根堆,如果当前元素比堆的根都元素大,那么一定要放到堆里来,用当前元素替换根元素(因为根的元素是最小的),然后调整堆。查找最小的K个元素用大根堆同理。
上代码:
#include <iostream>
using namespace std;
//在数组arr[1..size]中,使得以i为根的子堆保持大根堆的性质
void siftUp(int* arr, int i, int size)
{
if(i>=size)
return;
int lchild = 2*i,rchild = 2*i+1;
int largest = i;
if(lchild <= size && arr[lchild] > arr[largest])
largest = lchild;
if(rchild <= size && arr[rchild] > arr[largest])
largest = rchild;
if(largest != i)
{
int tmp = arr[i];
arr[i] = arr[largest];
arr[largest] = tmp;
siftUp(arr, largest, size);
}
return;
}
//find the least k elements, using max-root-heap
void findKLeastElements(int* arr, int k, int arrlength)
{
if(k >= arrlength)
{
cout<<"The original array length is less than "<<k<<","<<endl;
cout<<"so the original array is the least "<<arrlength<<" elements."<<endl;
return;
}
int* heaparr = new int[k+1];
for(int i = 0; i< k; ++i)
heaparr[i+1] = arr[i];
//build heap
for(int i = k/2; i >= 1; --i)//heaparr[k/2] is the last root
siftUp(heaparr,i,k);
//find the least k elements
for(int i = k; i < arrlength; ++i)
{
if(arr[i] < heaparr[1])
{
heaparr[1] = arr[i];
siftUp(heaparr, 1, k);
}
}
for(int i = 1; i <= k; ++i)
cout<<heaparr[i]<<" ";
cout<<endl;
delete []heaparr;
}
//在数组arr[1..size]中,使得以i为根的子堆保持小根堆的性质
void siftDown(int* arr, int i, int size)
{
if(i>=size)
return;
int lchild = 2*i,rchild = 2*i+1;
int least = i;
if(lchild <= size && arr[lchild] < arr[least])
least = lchild;
if(rchild <= size && arr[rchild] < arr[least])
least = rchild;
if(least != i)
{
int tmp = arr[i];
arr[i] = arr[least];
arr[least] = tmp;
siftDown(arr, least, size);
}
return;
}
//find the biggest k elements, using min-root-heap
void findKBiggestElements(int* arr, int k, int arrlength)
{
if(k >= arrlength)
return;
int* heaparr = new int[k+1];
for(int i = 0; i< k; ++i)
heaparr[i+1] = arr[i];
//build heap
for(int i = k/2; i >= 1; --i)//heaparr[k/2] is the last root
siftDown(heaparr,i,k);
//find the least k elements
for(int i = k; i < arrlength; ++i)
{
if(arr[i] > heaparr[1])
{
heaparr[1] = arr[i];
siftDown(heaparr, 1, k);
}
}
for(int i = 1; i <= k; ++i)
cout<<heaparr[i]<<" ";
cout<<endl;
delete []heaparr;
}
int main(int argc, char* argv[])
{
int x1[12]={30,22,45,34,67,100,-1,564,981,3,51,-33};
findKLeastElements(x1,1, 12);
findKBiggestElements(x1,3,12);
return 0;
}