每日一题之找出频率>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次不符,因此不可能有这样的情况。反过来说,用这样的办法,总是能够找到一对相同的数字!
实现的时候用循环队列来实现,可以降低一维移动数组的复杂度。
打群架。当k=2的时候,题解在这里。
http://blog.csdn.net/u011077606/article/details/42674197
当k>2的时候,每k个人打一次架,一次消耗k个人即可,这样,每次打架总是最多消耗1个出现频率最高的人。等群架打完以后,输出当前剩余人数最多的团体就是答案。
读入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>
相关文章推荐
- MY->> 读书笔记.每日更新();
- perl从/etc/passwd找出udi>500的用户
- <每日一句英语> 2012-9-21
- <每日一句英语>2012-9-18
- <每日一句英语> 2012-9-20
- 每日签到9.10-9.16<坚持的第一周>
- <每日一句英语>2012-9-14
- <每日一句英语> 2012-9-16
- <每日一句英语> 2012.9.11
- 进制转换,字符 <--> 数字
- 算法实现将一个输入的数字颠倒(输入12345->54321)
- <每日一句英语>2012-9-17
- 找出>=80%的前N项数据
- 金额转换,阿拉伯数字的金额转换成中国传统的形式如:(¥1011)->(一千零一拾一元整)输出
- 16进制字符-->10进制数字
- 职业素养.专业精神. ---&gt;论每日工作中的高效率
- 数字转英文(1200=> one thousand two HUNDRED)Sql函数
- <每日一句英语> 2012-9-22
- <每日一句英语> 2012-9-19
- <每日一句英语> 2012-9-13