Week12 作业 A - HDU 1209
题目描述:
给出n个数,现在想找出出现至少(n+1)/2次的数, 现在需要你帮忙找出这个数是多少?(输入保证N是奇数)
思路:
起初的想法是用unordered_map,没有什么问题。
但是我感觉对于这个题,map是不是大材小用?我简单搜索了一下,发现真的可以O(N)实现
因为出现次数最多的数超过了一半,所以用这个数去抵消其他数,最后剩下的数一定就是数量最多的数,当然抵消的过程很随意(无论怎么抵消,最后剩的肯定是最多的那个),但是要注意每个数只能被其他不同的数抵消一次
注意:N很大,用scanf能节约很多时间,我自己测试了一下,用cin是733ms,用scanf是171ms
代码:
使用unordered_map
#include <cstdio>
#include <iostream>
#include <map>
#include <unordered_map>
#include <string>
using namespace std;
unordered_map<int,int> mp;
int main()
{
int N;
while( scanf("%d",&N)==1 )
{
mp.clear();
for(int i=1;i<=N;i++)
{
int val;
scanf("%d",&val);
if(++mp[val]>=(N+1)/2)
{
cout<<val<<endl;
string s;
getline(cin,s);
break;
}
}
}
return 0;
}
更好的方法
#include <iostream>
using namespace std;
int main()
{
int N;
while(scanf("%d",&N)==1)
{
//ans==现在等待被抵消的数,cnt==等待被抵消的这个数有多少个,val==现在读取到的数
int ans=0,val=0,cnt=0;
for(int i=1;i<=N;i++)
{
scanf("%d",&val);
if(cnt==0) //没有被抵消的数了,把现在的数当作被抵消的数
{
ans=val;
cnt=1;
}
else
{
//还有被抵消的数,抵消或者积累
if(ans==val) cnt++;
else cnt--;
}
}
cout<<ans<<endl;
}
}

浙公网安备 33010602011771号