课堂作业——找水王

 题目:

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

思路:关键句子“水王的发帖数目超过了帖子数目的一半”

  我们可以简单的理解其实就是相当于找出一个一维数组中出现次数超过一半的元素。

(方法一)按照ID的大小排序,然后在统计每个ID出现的次数,则出现次数最大的就是水王。在思路的最开始标出了关键句子,那么也可以不用统计就能直接推断在中间的ID号是水王。但是再考虑时间复杂度就会发现,只要涉及排序遍历,时间复杂度至少为O(N*logN)。

(方法二)之后老师提出了要求,要缩短时间复杂度,想到了hash表,键值(Key)为数组中的ID,值(Value)为ID对应的次数,然后再直接遍历整个hash表,找出每一个ID在对应的位置处出现的次数,超过一半的就可以断定为水王。但这样时间复杂度为O(N),还需另开辟空间。

(方法三)比较相邻的ID,如果每次删除两个不同的ID(不管是不是那个出现次数超过一半的),在剩下的数中,要查找的ID数目也会超过总数的一半。因此在遍历数组的时候保存两个值:一个是数组中的ID,一个是次数。每当遍历下一个ID的时候,先要判断下一个和当前保存的是否相同,若相同则次数加1;若不同则次数减1。在判断如果次数为零,就保存下一个ID,并把次数设为1。因为水王的ID出现的次数比所有ID出现次数总和的一半还要多,那么它就是最后一次把次数设为1所对应的。

源代码:

#include<iostream.h>
int main()
{
    int i,temp,count;
    int arr[10]={7,7,3,7,0,7,1,7,1,7};
    temp=10;
    count=0;
    for(i=0;i<10;i++)
    {
        if(count==0)
        {
            temp=arr[i];
            count=1;
        }
     else if(temp==arr[i])    { count++;    }   else if(temp!=arr[i])   { count--;   } } cout<<"水王就是: "<<temp<<endl; return 0;  

运行结果:

总结:

  之前在写其他关于排序和遍历的程序时,除了数据结构课的实验其他一律没有考虑时间复杂度,在以前编写的博客中也提到过。这次老师当作题目的要求提出,也不得不考虑。有时候最快想到的方法不一定是最简单、最快速、最适用的。以前只会考虑是否能实现,现在应该考虑是否可以更优化。查了一些资料,想这类题是微软、Google等的面试题目,只要考点也是在思路和算法上,比较能开拓思维。

  还有一点就是这次作业光想着思路和算法,却忽视了实现过程中的细节,编出来了却频频出错,例如在修改数组中元素的顺序后却得到了不一样的结果,经检查发现问题出在if()的判断语句中,把“count==0”写成“count=0”,虽然只有一个“=”的差别,但是我却一直在纠结是不是方法错了,花了很多时间才解决。

原文地址:https://www.cnblogs.com/mumulucky/p/4448512.html