编程之美——发帖水王

题目:

Tango是微软亚洲研究院的一个实验项目。研究院的员工和实习生都很喜欢在Tango上面交流灌水。传说,Tango有一大“水王”,他不但喜欢发帖,还会恢复其他ID发的每个帖子。坊间风闻该“水王”发帖数目超过了帖子总数的一半。如果你有一个当前论坛上所有帖子(包括回帖)的列表,其中帖子作者的ID也在表中,你能快速找出这个传说中的Tango水王吗?

分析:

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

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

如果一个ID出现的次数超过总数的一半。那么,无论水王的ID是什么,这个有序的ID列表中的第N/2项(从0开始编号)一定会是这个ID。不必再次扫描列表。如果能够迅速定位到列表的某一项,除去排序的时间复杂度,后处理的需要的时间为O(1)。

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

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

public static int FindKingID (int [] ID,int N)
    {
        int BlogKing = 0;
        int nTimes,i;

        for(i = nTimes= 0;i<N;i++)
        {
            if(nTimes == 0)
            {
                BlogKing = ID[i];
                nTimes = 1;
            }
            else
            {
                if(BlogKing == ID[i])
                {
                    nTimes++;
                }
                else {
                    nTimes--;
                }
            }
        }
        return BlogKing;
    }

这个题目体现了计算机科学中很普遍的思想,就是如何把一个问题转化成规模较小的若干子问题。分治、递推和贪心都是基于这样的思路。在转化过程中,小问题跟原问题的本质上一致。同样我们可以将小问题转化为更小的问题。因此,转化过程是很重要的。像上面的这个题目,我们保证了问题的解在小问题中仍然具有与原问题相同的性质:

水王的ID在ID列表中的数量超过一半。转化的效率越高,转化之后问题规模缩小的越快,则整体的时间复杂度越低。

时间: 2024-10-01 15:49:35

编程之美——发帖水王的相关文章

编程之美2.3笔记:寻找发帖“水王”

<编程之美>2.3: Tango是微软亚洲研究院的一个试验项目.研究院的员工和实习生们都很喜欢在Tango上面交流灌水.传说,Tango有一大“水王”,他不但喜欢发贴,还会回复其他ID发的每个帖子.坊间风闻该“水王”发帖数目超过了帖子总数的一半.如果你有一个当 前论坛上所有帖子(包括回帖)的列表,其中帖子作者的ID也在表中,你能快速找出这个传说中的Tango水王吗? 当面试的时候我们遇到这样的问题,应该怎么去思考呢?读SICP的一个很大的收获是,学会抽象.贵族娱乐城 抽象 抽象就是从问题中提取

编程之美2.3: 寻找发帖水王

题目:传说,Tango有一大"水王",他不但喜欢发帖,还会回复其他ID发的帖子,发帖数目超过帖子总数的一半,如果你有一个当前论坛上所有帖子的列表,其中帖子作者的ID也在表中,你能快速找到这个传说中的Tango水王吗? 解题思路:由于水王的发帖数目超过一半,当每次删除两个不同ID的帖子时,水王占得帖子数目仍然大于剩下帖子的一半,重复整个过程,将ID列表中的ID总数降低,转化为更小的问题,从而得到最后水王的ID. #include <iostream> #include <

编程之美2.3 寻找发帖水王

这道题目由于不容易写测试用例,所以,可以把题目转换为:在一个数组中,有一个数字出现的次数超过了数组大小的一半,这和题目原意是一样的. 这道题目的思想是我们同时去掉数组中两个不一样的数字,那么,数组中原来存在的规律是不变的(仅针对这个题目). 好吧,还是先给出函数声明: /*2.3 寻找发帖水王*/ bool DutVerify(int*, int, int); int DutFindNumMoreThanHalf(int*, int); 可以看到,函数声明中多了一个:DutVerify,这个函数

编程之美--2.3

题目描述:寻找发帖水王,转换一下就是:给定一个数组,找出出现次数大于n/2的元素 思路: (1)排序,直接输出中间元素 (2)O(N),每次删除两个不同元素,注意代码实现 1 #include <iostream> 2 #include <queue> 3 #include <climits> 4 #include <algorithm> 5 #include <memory.h> 6 #include <stdio.h> 7 usi

主元素 寻找发帖水王

寻找发帖“水王” 题目是这样描述的:“水王”发帖的数目超过了所有帖子的一半,有各个帖子的作者ID,求这个水王的ID 编程之美给出了两种巧妙的解法 解法一:ID排序,那么ID列表中的N/2项即为要找的ID(还要排序,时间复杂度为O(NlogN)) 解法二:通过查找,每次从列表中除去两个不一样的ID,最后就可以得出这个ID,时间复杂度O(N).写法上也有技巧,不必非要找到一个不一样的在继续下去,如果下一个一样,那么用一个变量记录这个次数,把次数+1,遇见不一样的-1.例如1,1,2,3,4 初始va

【编程之美】目录

第1章  游戏之乐——游戏中碰到的题目 1.1 让CPU占用率听你的指挥 1.2 中国象棋将帅问题 1.3 一摞烙饼的排序 1.4 买书问题 第2章  数字之魅——数字中的技巧 2.1 求二进制中1的个数 2.2 不要被阶乘吓倒 2.3 寻找发帖"水王" 2.4 1的数目 2.5 寻找最大的K个数 2.6 精确表达浮点数 2.7 最大公约数问题 2.8 找符合条件的整数 2.9 斐波那契(Fibonacci)数列 2.10 寻找数组中的最大值和最小值 2.11 寻找最近点对 2.12

《编程之美》

自己也是才听老师的介绍,才从网上下载下<编程之美>这本书来阅读. 浏览其目录,发现这样的一本书正时我这个阶段所最需要的,现在大二,已经有了一定的基础,所以再看以前那些基础教程总觉得,太简单了.但是看太难的东西,又有好些知识没有学过,不理解.所以想<编程之美>这样一本,用到的知识比较基础,但是解题思路很新颖,可以开拓我们的视野,同时书中列出了源代码,只要自己愿意学习,可以迅速仿照例子做出程序,对于树立编程人员的自信心有很大帮助,同时短小的程序,可以迅速做出来,可以当做空闲时间的一种休

编程之美-分层遍历二叉树

问题:给定一个二叉树,要求按分层遍历该二叉树,即从上到下按层次访问该二叉树(每一层将单独输出一行),每一层要求访问的顺序为从左到右,并将节点依次编号.那么分层遍历如图的二叉树,正确的输出应该为: <span style="font-size:14px;">1 2 3 4 5 6 7 8</span> 书中还给出了问题2:打印二叉树中的某层次的节点(从左到右),其中根结点为第0层,成功返回true,失败返回false 分析与解法 关于二叉树的问题,由于其本身固有的

读书问题之《编程之美》 -----12061161 赵梓皓

我阅读的书是<编程之美> 刚开始的时候阅读序,就觉得控制cpu利用率这个问题很好玩,所以重点看了这部分和解决办法,问题也都大部分是这部分的.那么问题就来了(挖掘机技术xxx?中国山东找蓝翔) 咳咳,问题在下面: 1.关于问题的提出.(也是一点点建议) 本书的主要内容是告诉读者如何思考问题和解决问题.但是提出问题也是很重要的,正如爱因斯坦所说“提出一个问题往往比解决一个问题更重要”,很多面试题(比如井盖为啥是圆的)我觉得正常人很少会想到.所以,这个问题是怎么想出来的...我很好奇.也希望作者能够