Description
给你一个n个数的数列,其中某个数出现了超过n div 2次即众数,请你找出那个数。
Input
第1行一个正整数n。
第2行n个正整数用空格隔开。
Output
一行一个正整数表示那个众数。
Sample Input
5 3 2 3 1 3
Sample Output
3
Hint
100%的数据,n<=500000,数列中每个数<=maxlongint。
zju2132 The Most Frequent Number
这个题很简单,但是重要的是时间和内存限制!
第一次的代码:
使用map 编号离散化,累加编号对应的值,最后输出出现最多的编号对应的值
大约n*log(n) 的方法,竟然超时了.....
#include<stdio.h>
#include<string.h>
#include<map>
using namespace std;
const int maxn=500005;
int x[maxn],num[maxn],id[maxn];
int main()
{
int n;
while(~scanf("%d",&n))
{
map<int,int> map;
memset(num,0,sizeof(num));
memset(id,0,sizeof(id));
int cnt=1;
for(int i=1;i<=n;++i)
{
scanf("%d",&x[i]);
if(!map.count(x[i]))
{
id[cnt]=i;
map[x[i]]=cnt++;
}
++num[map[x[i]]];
}
int kase=0,tp=0;
for(int i=0;i<cnt;++i)
{
if(num[i]>tp)
{
kase=i;tp=num[i];
}
}
printf("%d\n",x[id[kase]]);
}
return 0;
}
实在想不到如何优化了,后来见到了大神的题解,瞬间惊呆了!!!!
如题目所说,其中有一个数出现的次数大于总数的一半!这是个关键条件!
因此,如果用这个数去抵消和这个数不相同的数,那么抵消到最后肯定会剩下这个数!
代码如下:
#include<stdio.h>
int main()
{
int n;
while(~scanf("%d",&n))
{
int tp,cnt=1,num=-1;
while(n--)
{
scanf("%d",&tp);
if(tp==num)//相等的累加
{
++cnt;
}
else//否则就减
{
--cnt;
if(!cnt)//全部被抵消了,证明这个数不是答案
{
num=tp;cnt=1;//重新选择目标
}
}
}
printf("%d\n",num);
}
return 0;
}