解法零:
首先想到堆排序
假设从十个数中寻找三个最大的数
将前三个数建立小根堆(用数组a记录),遍历剩下的(10 - 3)个数字,对其做如下循环:
1.取出下一个数字(假设是i),将其与小根堆中的根比较,若其小于根节点,则不作任何处理,直接处理剩余数字中的下一个
2.若大于根节点,则删除小根堆中的根节点,将i插入a中
3.处理剩余数字中的下一个
遍历完成后,输出小根堆a,即为所求的最大的k个数
code:
#include "stdafx.h"
#include <iostream>
using namespace std;
void Swap(int &a,int &b)
{
int temp = a;
a = b;
b = temp;
}
void Print(int *a,int n)
{
for(int i = 0 ; i < n ; ++i)
cout<<a[i]<<" ";
cout<<endl;
}
void MinHeapFixDown(int *a,int i,int n)
{
int j = 2 * i +1;
int temp = a[i];
while(j < n)
{
if(j+1<n&&a[j]>a[j+1])
j++;
if(temp < a[j])
break;
a[i] = a[j];
i = j;
j = i*2+1;
}
a[i] = temp;
}
bool MinHeapDelNum(int *a,int n,int i)
{
if(i < a[0])
return false;
Swap(a[0],a[n]);
MinHeapFixDown(a,0,n);
return true;
}
void MinHeapFixUp(int *a,int i)
{
for(int j = (i - 1) / 2 ; (j >= 0)&&(i != 0)&&(a[j] > a[i]) ; i = j , j = (i - 1) / 2)
Swap(a[i],a[j]);
}
void MinHeapAddNum(int *a,int n,int i)
{
a[n] = i;
MinHeapFixUp(a,n);
}
void heap(int *a,int aNum,int *p,int pNum)
{
for(int i = 0 ; i < pNum ; ++i)
{
if(i < aNum)
MinHeapAddNum(a,i,p[i]);
else
{
if(MinHeapDelNum(a,aNum - 1,p[i]) == true)
MinHeapAddNum(a,aNum - 1,p[i]);
}
}
}
int _tmain(int argc, _TCHAR* argv[])
{
int a[3] = {0};
int p[10] = {4,6,2,5,7,11,54,35,66,1};
heap(a,3,p,10);
Print(a,3);
return 0;
}
书上的解法:
解法一:排序,取前K个数
解法二:
快排&递归,每次将待排数据分为左右两组Sa和Sb
1.Sa中元素个数小于K,数组S中最大的K个数:Sa的全部和Sb中最大的K-|Sa|
2.Sa中元素个数大于等于K,返回Sa中最大的K个数
解法三:???
解法四:即解法零
解法五:当所有N个数都是正整数且取值范围不大时,可考虑直接使用数组记录每个整数出现次数得出结论