三人行设计了一个灌水论坛。信息学院的学生都喜欢在上面交流灌水,传说在论坛上有一个“水王”,他不但喜欢发帖,还会回复其他ID发的每个帖子。坊间风闻该“水王”发帖数目超过了帖子数目的一半。
如果你有一张当前论坛的帖子(包括回帖)列表,其中帖子的作者的ID也在其中,你能快速的找到这个传说中的水王吗?
思路分析:
因为数据量及其庞大,而水王的发帖量超过了一半,所以必有两次水王的id号记录是相邻的,所以两个相邻的元素比较,如果一样的话都留一个,不一样的全部删掉,最后剩下的一定是水王的id。这个思路看上去简单,但是对于一维数组来说删除是一种时间上很不合适的操作(用链表的话我又懒得写那么麻烦。。。),所以应该找一种类似于删除的方法来完成具体实现。说白了这个题这个题得找到一个合适的flag值来做标记,设key这个变量用来记录当前水王id的备选值。接下来就是从头到尾开始循环。第一次循环key值就设置成当前的id即可,flag值置为1。从第二次循环开始就要比较了,如果当前的id和key值相同,则flag自增为1,否则自减1。在后面的循环中,如果出现了flag为0的情况,说明当前水王的备选值key不一定正确,此时直接置成当前的id号即可,flag值仍然置为1。重复上述过程,知道循环结束。这样做的道理就是,由于水王发帖量超过了一半,所以用水王的id去一个一个抵消别人的id号,最后还是能够剩下水王的id号,flag的自减变化就模拟了这个抵消的过程。
最后,这个题是编程之美上的一个问题,来源貌似是微软亚洲研究院的一个论坛。
1 int main(){ 2 system("title 11找水王"); 3 //这数据我也懒得手动输入了,随便指定一组好了。。。 4 int a[7] = {1,1,1,2,5,4,1}; 5 int round = 0; 6 int key = 0; 7 for (int i = 0; i < 7; ++i){ 8 if (round == 0 || i == 0){ 9 key = a[i]; 10 round = 1; 11 } 12 else if (key == a[i])round++; 13 else if (key != a[i])round--; 14 } 15 cout <<key<< endl; 16 return 0; 17 }
总结:
没啥好总结的,不是很常规的算法题目,没什么普适性的经验可以总结,最多就是培养一种感觉,做这种题心蛮累的。。。