《寻找发帖“水王”》代码的理解

题目:有一个人在论坛上发的帖子数超过了帖子总数的一半,每个帖子作者都有ID,怎么样迅速找出这个水王?

解法一:先将所有ID排序,再扫描一遍求得每个ID出现的次数。

解法二:先将所有ID排序,在N / 2处的ID一定是水王的。

解法三:

Type Find(Type* ID, int N)
{
    Type candidate;
    int nTimes, i;
    for(i=nTimes=0;i<N;i++)
    {
       if(nTimes==0)
       {
          candidate = ID[i];
          nTimes = 1;
       }
       else
       {
          if(candidate == ID[i])
            nTimes++;
          else
            nTimes--;
       }
    }
    return candidate;
}

总体思想是:遍历一次整个列表,利用一个计数器,每遇到两个不同的ID,就将它们排除在考虑之外。不管排除的这两个ID是否包含水王的ID,在每次排除之后,水王的ID次数还是超过总数的一半。

在代码里面,candidate变量最后返回的是水王的ID。nTimes是指当前candidate对应的ID在与不同ID抵消后的重数。比如有XXXYZ序列。那么当i=2时,nTimes=3,说明candidate(X)当前抵消后有3个重数;当i=3时,那么nTimes=2,说明遇到了一个不同的ID,导致candidate和这个不同ID被排除在考虑之外了。当i=4时,nTimes=1,这说明X这个ID的数量是超过一半的,因为它与所有不同的ID抵消之后还有重数。candidate最后返回的就是与所有ID抵消后重数还大于0的那个ID。

再考虑YXZXX序列。这次candidate换了几次,分别是Y,Z和最后一个X。

  Y X Z X X
candidate Y Y Z Z X
nTimes 1 0 1 0 1

最后考虑YZXXX序列。

  Y Z X X X
candidate Y Y X X X
nTimes 1 0 1 2 3

题目的关键是“超过一半”,所以可以通俗地认为水王的ID经得起抵消。

posted @ 2013-12-05 10:09  XIAOSHUA  阅读(214)  评论(0编辑  收藏  举报