来自编程之美
方法一:sort,第n/2个数必定是那个数;
fast select,选择第n/2个数;
方法二:
int Find(int *id,int N)
{
int candidate;
int nTimes,i;
for(i=nTimes=0;i<N;i++)
{
if(nTimes==0)
{
candidate=id[i];
nTimes=1;
}
else
{
if(candidate==id[i])
nTimes++;
else
nTimes--;
}
}
return candidate;
}
扩展1:找出正好出现一半的那个数
int Find(int* a, int N)
{
int candidate1,candidate2;
int nTimes1, nTimes2, i;
for(i = nTimes1 = nTimes2 =0; i < N; i++)
{
if(nTimes1 == 0)
{
candidate1 = a[i], nTimes1 = 1;
}
else if(nTimes2 == 0 && candidate1 != a[i])
//注意:这里的判断条件加上第二个变量是否等于第一个变量的判断
{
candidate2 = a[i], nTimes2 = 1;
}
else
{
if(candidate1 == a[i])
nTimes1++;
else if(candidate2 == a[i])
nTimes2++;
else
{
nTimes1--;
nTimes2--;
}
}
}
return nTimes1>nTimes2?candidate1:candidate2;
}
扩展2:如果论坛发帖ID列表中,有三个发帖很多的ID,他们的发帖数目都超过了帖子总数N的1/4,你能快速找到它们吗?
void find3(int a[],int ret[],int n)
{
int cnt[3] = {0};
int i,j,k;
ret[0] = ret[1] = ret[2] = INT_MIN;
for(i = 0; i < n;i++)
{
for(j = 0; j < 3;j++)
if(ret[j] == a[i])
{
cnt[j]++;
break;
}
if(j == 3)
{
for(k = 0; k < 3;k++)
if(cnt[k] == 0)
{
cnt[k] = 1;
ret[k] = a[i];
break;
}
if(k == 3)
cnt[0]--,cnt[1]--,cnt[2]--;
}
}
}