课堂练习-找水王

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了课堂练习-找水王相关的知识,希望对你有一定的参考价值。

问题描述:

   •三人行设计了一个灌水论坛。信息学院的学生都喜欢在上面交流灌水,传说在论坛上有一个“水王”,他不但喜欢发帖,还会回复其他ID发的每个帖子。坊间风闻该“水王”发帖数目超过了帖子数目的一半。
   •如果你有一张当前论坛的帖子(包括回帖)列表,其中帖子的作者的ID也在其中,你能快速的找到这个传说中的水王吗?
 
问题分析:
   分析问题发现,帖子列表好比一个一维数组arry,arry[0]的内容就是第0贴子的发帖人,问题就可以抽象成:一个长度为N一维数组中有大于等于[N/2]+1个元素相同(一半以上元素相同),找出相同的元素。
 
设计思想:
   可以采用两两消除法,具体实现就是对数组中不同的两个元素进行消除,最终剩下来的一定就是要找的那个元素。在程序实现中需要按序(顺序或者倒序)进行操作,但原理是相同的。对数组遍历一遍,在遍历到arry[i]个元素时,count记录前arry[0]-arry[i-1]个元素两两消除后剩余未消除的个数(这剩余的count个元素肯定是相同的),ID记录着未消除元素的内容,最终ID就是所求元素。
 
程序代码:
//2016/5/17
#include<iostream>

void main()
{
    int i = 0;
    int count = 0;  //用于记录数组前N个数中的元素两两不同则消除的剩余数
    int ID;  //用于记录ID
    int arry[] = { 1, 2, 3, 1, 4, 1, 1, 1, 8, 1 ,6 ,1 };   //帖子列表,下标是帖子ID,内容是发帖人ID
    
    for (; i < sizeof(arry)/sizeof(arry[0]); i++)
    {
        
        if (count == 0)    //如果count减为0,代表前i-1个ID两两消除,更新ID和count
        {
            ID = arry[i];
            count = 1;
        }
        else              //否则继续与下个元素进行两两消除或者增加相同元素个数
        {
            if (ID == arry[i])  //增加相同元素的个数
            {
                count++;
            }
            else    //消除
            {
                count--;
            }
        }
    }
    //输出水王ID
    std::cout << "水王的ID是 " << ID << std::endl;
}

实现截图:

 arry[] = { 1, 2, 3, 1, 4, 1, 1, 1, 8, 1 ,6 ,1 };

技术分享

arry[] = { 2, 5, 6, 6, 5, 5, 5 };

技术分享

个人总结:

   这个问题有很多解法,最简单的就是对数组中的每一个元素的出现次数进行计数,最后再找到出现次数最多的那个元素,但是这种方法是要以牺牲时间和空间作为代价的,其实如果能找出问题所潜藏的一面,加以利用方法往往可以简单很多,就比如本例。然而,这也正是困难所在。

以上是关于课堂练习-找水王的主要内容,如果未能解决你的问题,请参考以下文章

课堂练习--找水王

课堂练习--“找水王续"

课堂练习-找水王

课堂练习-找水王

课堂练习……找水王

课堂练习-找水王