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;
	}
}

  

猜你喜欢

转载自www.cnblogs.com/qingoba/p/12983857.html