答案_寻找发贴“水王”
来源:互联网 发布:淘宝首页轮播广告费 编辑:程序博客网 时间:2024/04/29 12:43
分析与解法
首先想到的是一个最直接的方法,我们可以对所有ID进行排序。然后再扫描一遍排好序的ID列表,统计各个ID出现的次数。如果某个ID出现的次数超过总数的一半,那么就输出这个ID。这个算法的时间复杂度为O(N * log2N + N)。
如果ID列表已经是有序的,还需要扫描一遍整个列表来统计各个ID出现的次数吗?
如果一个ID出现的次数超过总数N的一半。那么,无论水王的ID是什么,这个有序的ID列表中的第N/2项(从0开始编号)一定会是这个ID(读者可以试着证明一下)。省去重新扫描一遍列表,可以节省一点算法耗费的时间。如果能够迅速定位到列表的某一项(比如使用数组来存储列表),除去排序的时间复杂度,后处理需要的时间为O(1)。
但上面两种方法都需要先对ID列表进行排序,时间复杂度方面没有本质的改进。能否避免排序呢?
如果每次删除两个不同的ID(不管是否包含“水王”的ID),那么,在剩下的ID列表中,“水王”ID出现的次数仍然超过总数的一半。看到这一点之后,就可以通过不断重复这个过程,把ID列表中的ID总数降低(转化为更小的问题),从而得到问题的答案。新的思路,避免了排序这个耗时的步骤,总的时间复杂度只有O(N),且只需要常数的额外内存。伪代码如下:
代码清单2-8
Type Find(Type* ID, int N)
{
Type candidate;
int nTimes, i;
for(i = nTimes = 0; i < N; i++)
{
if(nTimes == 0)
{
candidate = ID[i], nTimes = 1;
}
else
{
if(candidate == ID[i])
nTimes++;
else
nTimes--;
}
}
return candidate;
}
在这个题目中,有一个计算机科学中很普遍的思想,就是如何把一个问题转化为规模较小的若干个问题。分治、递推和贪心等都是基于这样的思路。在转化过程中,小的问题跟原问题本质上一致。这样,我们可以通过同样的方式将小问题转化为更小的问题。因此,转化过程是很重要的。像上面这个题目,我们保证了问题的解在小问题中仍然具有与原问题相同的性质:水王的ID在ID列表中的次数超过一半。转化本身计算的效率越高,转化之后问题规模缩小得越快,则整体算法的时间复杂度越低。
扩展问题
随着Tango的发展,管理员发现,“超级水王”没有了。统计结果表明,有3个发帖很多的ID,他们的发帖数目都超过了帖子总数目N的1/4。你能从发帖ID列表中快速找出他们的ID吗?
相关资源: 《编程之美》编辑部 | 《编程之美》豆瓣 | 《编程之美》互动网购买 | 作者Blog 作者豆瓣
- 答案_寻找发贴“水王”
- BOP - 寻找发贴‘水王’
- 面试真题:寻找发贴“水王”
- 【编程之美】2.3 - 寻找发贴"水王"
- 寻找答案
- 微软《编程之美》:寻找发贴“水王” 及 其扩展问题
- 《编程之美》学习笔记——2.3寻找发贴“水王”
- 寻找发贴水王
- 寻找得到答案的方向
- 普及版循环数组发答案!
- 答案_饮料供货
- 答案_最大公约数问题
- 答案_最大公约数问题
- 你必须自己去寻找答案
- 我们一起走,寻找自己的答案
- 枚举法_寻找三位数
- Android开发_发短信
- 1063 -- 发奖学金咯^_^
- 周末了
- 自信的秘密
- Java程序员面试时常见的问题
- 一个有关mySQL 触发器激活的错误 #1442
- 感悟那些重要与不重要的
- 答案_寻找发贴“水王”
- 面试真题_精确表达浮点数
- c# 线程
- 孔目胡
- ASP.NET缓存概念及其应用浅析
- 壮志多坎坷(9.12)
- 忘记管理员密码怎么办,教你好办法,在线解决MD5加密算
- 关于Asp.net 缓存笔记(一)
- 关于String 详解