您的位置:首页 > 其它

找第K大数的一些小算法技巧;

2010-05-21 17:59 253 查看
#include <stdio.h>
#include <stdlib.h>
#define Siz 3
#define Min -10000

int minHeap[3]={Min};

void updateHeap(int x)
{
if(x>minHeap[0])
{
minHeap[0]=x;
int p=0;
while(p<3)
{
int q=2*p+1;
if(q>=3)
{
break;
}
if(q<2&&minHeap[q]>minHeap[q+1])
{
q+=1;
}
if(minHeap[p]>minHeap[q])
{
int tmp=minHeap[p];
minHeap[p]=minHeap[q];
minHeap[q]=tmp;
p=q;
}
else
{
break;
}
}
}
}

void get3rdScore()
{
int n,sc;
scanf("%d",&n);
int i=0;
for(;i<n;++i)
{
scanf("%d",&sc);
updateHeap(sc);
}
if(minHeap[0]==Min)
{
printf("No such score !/n");
return;
}
printf("%d",minHeap[0]);
}

int main()
{
get3rdScore();
return 0;
}


 

上述算法功能:

 

输入一系列可重复的数, 找出第K大的数, 重复数字也算作1个.

 

例如: 2 2 1 4, 第3大的数字是2, 而不是1.

 

思想:需要找第K大数,只需要建立一个容量为K的最小堆,初始化所有元素都无穷小.

每次读取一个数据,

如果这个数据比堆顶元素大,那么它可以替代堆顶,并用updateHeap维持最小堆的性质.

如果这个数据比堆顶元素小,那么它一定小于所有堆内的元素,所以不必操作.

如果这个数据和堆顶元素一样大, 由于堆顶元素是堆内最小的元素, 所以不必操作,因为如果插入一个与堆顶一样大的元素去替换某一个结点,被替换的结点不会比插入的元素小,所以不能替换.

 

所以算法主要就是围绕一个最小堆来做的,思想很简单.

 

稍后补充另一个算法,在此基础上不计算重复的第K大元素.

 

#include <stdlib.h>
#include <stdio.h>

//100bits

unsigned int flag[4]={0};

bool getCheck(int sc)
{
int is=(1<<(31-sc%32))&flag[sc/32];
if(is!=0)
{
return true;
}
else
{
return false;
}
}

void setCheck(int sc)
{
flag[sc/32]|=(1<<(31-sc%32));
}

int main()
{
int n,sc,cnt;
scanf("%d",&n);
while(n!=0)
{
cnt=0;
for(int i=0;i<n;++i)
{
scanf("%d",&sc);
setCheck(sc);
}
for(int j=100;j>=0;--j)
{
if(getCheck(j)==true)
{
++cnt;
}
if(cnt==3)
{
printf("%d/n",j);
break;
}
}
if(cnt!=3)
{
printf("No such score !/n");
}
scanf("%d",&n);
}
}


 

这个算法的思想是利用空间换时间,当然空间也是相当的小....只要101个位就可以了.

 

逐次输入成绩,给成绩对应的位做标记.  最后从100分开始计数,一旦计数到达3次,就打印出那个成绩就是第3(不重复)大成绩.

 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法 include