答案_寻找发贴“水王”

来源:互联网 发布:淘宝首页轮播广告费 编辑:程序博客网 时间:2024/04/29 12:43

分析与解法

首先想到的是一个最直接的方法,我们可以对所有ID进行排序。然后再扫描一遍排好序的ID列表,统计各个ID出现的次数。如果某个ID出现的次数超过总数的一半,那么就输出这个ID。这个算法的时间复杂度为ON * log2N + N)。

如果ID列表已经是有序的,还需要扫描一遍整个列表来统计各个ID出现的次数吗?

如果一个ID出现的次数超过总数N的一半。那么,无论水王的ID是什么,这个有序的ID列表中的第N/2项(从0开始编号)一定会是这个ID(读者可以试着证明一下)。省去重新扫描一遍列表,可以节省一点算法耗费的时间。如果能够迅速定位到列表的某一项(比如使用数组来存储列表),除去排序的时间复杂度,后处理需要的时间为O1)。

但上面两种方法都需要先对ID列表进行排序,时间复杂度方面没有本质的改进。能否避免排序呢?

如果每次删除两个不同的ID(不管是否包含“水王”的ID),那么,在剩下的ID列表中,“水王”ID出现的次数仍然超过总数的一半。看到这一点之后,就可以通过不断重复这个过程,把ID列表中的ID总数降低(转化为更小的问题),从而得到问题的答案。新的思路,避免了排序这个耗时的步骤,总的时间复杂度只有ON),且只需要常数的额外内存。伪代码如下:

代码清单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;

}

在这个题目中,有一个计算机科学中很普遍的思想,就是如何把一个问题转化为规模较小的若干个问题。分治、递推和贪心等都是基于这样的思路。在转化过程中,小的问题跟原问题本质上一致。这样,我们可以通过同样的方式将小问题转化为更小的问题。因此,转化过程是很重要的。像上面这个题目,我们保证了问题的解在小问题中仍然具有与原问题相同的性质:水王的IDID列表中的次数超过一半。转化本身计算的效率越高,转化之后问题规模缩小得越快,则整体算法的时间复杂度越低。

扩展问题

随着Tango的发展,管理员发现,“超级水王”没有了。统计结果表明,有3个发帖很多的ID,他们的发帖数目都超过了帖子总数目N1/4。你能从发帖ID列表中快速找出他们的ID吗?

相关资源:

《编程之美》编辑部 | 《编程之美》豆瓣 | 《编程之美》互动网购买 | 作者Blog

作者豆瓣

 

 

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 兔子的睾丸烂了怎么办 梗阻性无精穿刺取得精子不好怎么办 甲状腺做完穿刺后是恶性怎么办 硬了之后睾丸痛怎么办 腋下胯间颜色深怎么办 当兵前上班有社保怎么办 别人背后害我我怎么办 左侧胸明显大于右侧胸怎么办 婴儿拉大便次数多怎么办 公鸽子不会踩蛋怎么办 生殖器套东西取不下来怎么办 婴儿成蛋蛋的皮好长怎么办 丈夫总要害自己该怎么办 脚背踢肿了怎么办很疼 踢沙袋脚背伤了怎么办 脚y子烂了怎么办 掐喉咙那会痒会咳嗽怎么办 掐到婴儿脖子了怎么办 孩子胳膊不小心烫破皮了怎么办 孩子嘴角磕破了怎么办 电话不小心拒接了怎么办 手机微信不小心碰到语言英文怎么办 手机微信不小心碰到英文说话怎么办 不小心碰到宝宝卤门怎么办 不小心碰到婴儿头顶囟门怎么办 重要部位被踢了怎么办 吃了带刺的葡萄怎么办 小孩子老是去厕所大便怎么办 家人偷了我的钱怎么办 小孩打闹踢到要害怎么办 腿上汗毛孔没开都是点点怎么办 脸蛋澡巾擦破了怎么办 婴儿后背用擦澡巾擦红了怎么办 搓澡皮肤搓破了怎么办 搓背搓的脖子红痒怎么办 上班迟到1个小时怎么办 想家想的都哭怎么办 想学手艺被骗学费怎么办 小腿肚后面筋和肌肉压痛怎么办 尿道囗和屁股眼中间长疮怎么办? 2个多月的宝宝蛋蛋上有个包怎么办