问题描述:某一贴吧有一个超级大“水王”,他不但喜欢发帖,还喜欢回复其他ID发的帖子,传闻该“水王”发的帖子
数量超过了帖子总数的一半。如果你有一个当前贴吧的所有帖子的列表,其中帖子的作者ID也在表中,如何快速找出这个超级大“水王”?
分析与解法:
最直接的方法就是,对所有的ID进行排序,然后统计出每个ID出现的次数,如果某个ID出现的次数超过总数的一半,则此ID就是“水王”。这种算法的时间复杂度为O(n*logn + n)。
如果ID已经是有序的,那么无论“水王”的ID是什么,这个有序的ID列表中的第n/2项一定是“水王”的ID,也就不用进行扫描统计。如果能够迅速定位到列表中的某一项(比如说列表是用数组存储的),除去排序的时间复杂度,后续处理时间复杂度为O(1)。
上述两种算法都需要对ID进行排序,时间复杂度方面没有本质的改变。有没有一种方法可以避免排序呢?如果每次删除两个不同的ID(无论这个ID是否是“水王”),在剩下的ID列表中,“水王”ID的出现的次数任然是超过总数的一半,可以不断重复这个过程,将ID列表的总数不断减少,直到能找到这个水王。
代码如下:
Type find(Type *ID,int n)
{
Type candidate;
int i, times;
for (i = times = 0; i < n;i++)
{
if (times == 0)
{
candidate = ID[i];
times = 1;
}
else
{
if (candidate == ID[i])
times++;
else
times--;
}
}
return candidate;
}