一、题目

      三人行设计了一个灌水论坛。信息学院的学生都喜欢在上面交流灌水,传说在论坛上有一个“水王”,他不但喜欢发帖,还会回复其他ID发的每个帖子。坊间风闻该“水王”发帖数目超过了帖子数目的一半。 如果你有一张当前论坛的帖子(包括回帖)列表,其中帖子的作者的ID也在其中,你能快速的找到这个传说中的水王吗?

二、设计思想:

     由于该“水王”发帖数目超过了帖子数目的一半,可以通过相邻两个帖子的作者ID是否相同来寻找。如果相邻两个ID不同,则将两个ID略过;若相等,则判断之前是否有怀疑是“水王”的ID,如果没有,则当前ID可以可以看做是目前的“水王”,如果已经有怀疑是水王的ID,则判断当前ID与怀疑是水王的ID是否相同,如果不同,则减少一次目前为水王的ID连续出现的次数记录,若相同,则增加一次水王ID连续出现的次数。继续下面的比较,知道结束。如果帖子数目为单数,则要考虑最后一个ID。通过上述思想,可以知道时间复杂度为O(n)。

三、代码实现

 

#include<iostream>
using namespace std;

int main()
{
    int a[10000],length=-1,i;//a[10000]用来存储每个帖子的作者ID,length用来记录帖子的数量
    int b[2];
    //b[0]用来记录当前认为的“水王”的ID
    //b[1]用来记录记录当前认为的“水王”相对于其他用户连续出现多出来的次数

    while(length<1)
    {
        cout<<"请输入帖子的数量:"<<endl;
        cin>>length;
    }

    cout<<"请依次输入每个帖子的作者ID:"<<endl;
    for(i=0;i<length;i++)
    {
        cin>>a[i];
    }
    b[0]=a[0];
    b[1]=0;
    for(i=0;i<length-1;i++)
    {
        if(a[i]==a[i+1])
        {
            if(b[1]>0)//当前查找出来的“水王”
            {
                if(a[i]==b[0])
                { 
                    b[1]++;
                }
                else
                {
                    b[1]--;
                }
            }
            else//当前还没有查找出水王
            {
                b[0]=a[i];
                b[1]++;
            }
            i++;
        }
        else if(a[i]!=a[i+1])
        {
            i++; 
        }
        if(i==length-2)//对于帖子数目出现但是单数的情况,对最后一个数进行处理
        { 
            if(b[1]==0)
            { 
                b[0]=a[i+1];
            }
        }
    }
    cout<<"“水王”ID为:"<<b[0]<<endl;
    return 0;
}

四、实现截图

 例子1:假设只有一个ID

例子2:假设帖子数为偶数

例子3:假设帖子数为奇数

例子4:假设只有开始有连续出现的ID

例子5:假设只有末尾出现连续出现的ID

五、个人总结

       这次实验,刚开始看到这个题目时,我不怎么明白它的意思。在老师说出“比较相邻两个ID是否相同,相同则保留,不相同则删除”时,我有了自己的想法。一开始,我想的是把不同的相邻两个数删去,相同的则保留一个,然后再进行比较,可是这样时间复杂度比较大,还有错误。最后我侧重于思考水王发帖数超过帖子数的一半,则水王ID连续出现的次数大于等于其他用户连续出现的次数之和,通过这个我想到了通过记录当前怀疑为水王的ID连续出现的次数相对于其他用户目前连续次数之和多余的次数来找到水王。通过这次实验,我学会了控制时间复杂度来编写程序,在编写程序解决问题时,我们要读懂问题的核心,找到问题的突破口,从而来解决问题。