您的位置:首页 > 其它

每日一题之找出频率>1/k的数字

2015-01-21 08:38 204 查看
题意描述:

读入n个数字,这n个数字中,有一个数字出现的次数>n/k,剩下的每一个数字都是单独出现的,求那个数字是多少?

k<=10,空间限制到不能开100以上的数组。

骗分思路:

因为只有答案的那个数字是出现次数>=1次的,那么在读入的时候记录读入的前一个数字,判断这个数字和上一个数字是不是相等,如果相等,则必然是答案。这样子做,已经可以通过绝大多数(几乎100%的)随机数据了,但是依然不能保证AC,例如1 2 1 3 1 4 1 5 1这样的数据。

思路1:

既然只判断一个不行,那就多开点数组,开个大小为80的数组,每次读入一个数字判断和前80个是否有相等的,如果有就输出。

从理解上来讲,这样可以提高找到答案的正确率,实际上,这样的思路是100%正确的,来看一下证明:

假设我们读入的数字是K,而我们比较了任何一个数字和它之前的(K)个,发现都没有相等的。

那么,重复的那个数字出现的次数,最多最多只能有N/(K+1)+1个<题目上说的出现次数。例如,当N=8,K=2的时候,对每个数字比较前2个都没有相等,则这个序列只可能是:

X 1 2 X 3 4 X 5

与题目描述的出现频率>8/2=4次不符,因此不可能有这样的情况。反过来说,用这样的办法,总是能够找到一对相同的数字!

实现的时候用循环队列来实现,可以降低一维移动数组的复杂度。
<span style="font-size:14px;">for (int i=0;i<n;i++)
{
int t=i%(k+1);
cin>>arr[t];
for (int j=0;j<=k;j++)
if (j!=t && arr[j]==arr[t])
{
cout<<arr[t]<<endl;
return 0;
}

}</span>
思路2:

打群架。当k=2的时候,题解在这里。
http://blog.csdn.net/u011077606/article/details/42674197
当k>2的时候,每k个人打一次架,一次消耗k个人即可,这样,每次打架总是最多消耗1个出现频率最高的人。等群架打完以后,输出当前剩余人数最多的团体就是答案。

<span style="font-size:14px;">memset(num,0,sizeof(num));
cin>>n>>k;
int zong=0,flag=0;
for (int i=1;i<=n;i++)
{
cin>>t;
flag=0;
for (int j=0;j<k;j++)
if (arr[j]==t && num[j]>0)
{
num[j]++;
flag=1;
break;
}
if (flag) continue;
if (zong+1<k)
{
zong++;
for (int j=0;j<k;j++)
if (num[j]==0)
{
num[j]=1;
arr[j]=t;
break;
}
continue;
}
else
{
for (int j=0;j<k;j++)
if (num[j]>0)
{
num[j]--;
if (num[j]==0) zong--;
}
}
}
int zuida=0;
for (int j=0;j<k;j++) zuida=max(zuida,num[j]);
for (int j=0;j<k;j++) if (zuida==num[j]) cout<<arr[j]<<endl;</span>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: