题目描述:
给出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; } }