您的位置:首页 > 编程语言

[编程之美] PSet2.3 寻找发帖“水王”

2014-07-28 18:49 239 查看
问题描述:

Tango是微软亚洲研究院的一个试验项目。研究院的员工和实习生们都很喜欢在Tango上面交流灌水。传说,Tango有一大“水王”,他不但喜欢发贴,还会回复其他ID发的每个帖子。坊间风闻该“水王”发帖数目超过了帖子总数的一半。如果你有一个当前论坛上所有帖子(包括回帖)的列表,其中帖子作者的ID也在表中,你能快速找出这个传说中的Tango水王吗?

解题思路:

思路一:

    书中第一种方法是先对ID进行排序,再遍历排序后的ID列表,统计每个ID出现的次数,如果有一个ID出现次数超过总数一半,从而寻找到最大次数的ID。对这个排好序的ID列表查找“水王”的ID并不需要扫描一遍所有序列找最大,或是找总数超过一半的ID,可以直接定位到第N/2项(下标从0开始)就可以了。O(NlogN)+O(1)

    需要对这么大的一个列表进行统计排序非常麻烦,有一种方式可以避免排序:

思路二:

    缩小问题规模,分而治之:每次删除两个不同的ID(不管是否包含“水王”的ID),那么在剩下的ID列表中,“水王”ID出现的次数必然仍然超过总数的一半。

    不断重复这个过程,把ID列表中ID的总数降低,转化为更小的问题。耗时O(N),只需常数的额外内存。

    代码如下:

//下面的代码是寻找发帖水王的代码
//输入:ID数组,用Type *ID表示。元素数据类型为Type,以及数组大小N
//输出:ID水王的ID号
//方法:交替的抵消两个相邻的不同ID号,如果相同ID则让标志位+1
Type findShuiWang(Type *ID , int N)
{
Type candidate ;
int nTimes = 0;//标志位
for(int i=0 ; i<N ; i++){
if(nTimes == 0){
candidate = ID[i];
nTimes++;
}
else{
if(ID[i] == candidate){
nTimes++;
}
else{
nTimes--;
}
}
}
return candidate;
}

扩展问题:

随着Tango的发展,管理员发现,“超级水王”没有了。统计结果表明,有3个发帖很多的ID,他们的发帖数目都超过了帖子总数目N的1/4。你能从发帖ID列表中快速找出他们的ID吗?

这个扩展问题还是上题所述的对偶问题,由于这三个水王每个ID出现次数都超过1/4,所以非水王ID不到1/4,也就是水王ID:非水王ID > 3:1,因此可以设定三个标志位nTmes[3]进行统计,如果出现一个与当前三个候选者均不同的ID号,则让当前三个候选nTimes[i]--;最终nTimes[i]不为0的就是最终的三个水王。时间复杂度O(N)

typedef int Type;
void Find(Type* ID, int N ,Type candidate[3])
{
const Type ID_NULL = -1;//定义一个不存在的ID
int nTimes[3], i;
nTimes[0]=nTimes[1]=nTimes[2]=0;
candidate[0]=candidate[1]=candidate[2]=ID_NULL;
for(i = 0; i < N; i++)
{
if(nTimes[0]==0)
{
nTimes[0]=1;
candidate[0]=ID[i];
}
else if(nTimes[1]==0)
{
nTimes[1]=1;
candidate[1]=ID[i];
}
else if(nTimes[2]==0)
{
nTimes[2]=1;
candidate[2]=ID[i];
}
else if(ID[i]==candidate[0])
{
nTimes[0]++;
}
else if(ID[i]==candidate[1])
{
nTimes[1]++;
}
else if(ID[i]==candidate[2])
{
nTimes[2]++;
}
else
{
nTimes[0]--;
nTimes[1]--;
nTimes[2]--;
}
}
return;
}

int main()
{
Type ID[] = {0,4,1,4,0,4,1,4,1,0,3,3,0,3,3,3};
Type candidate[3];

Find(ID , 16 , candidate);
for(int i=0 ; i<3 ; i++)
cout << candidate[i]<<" ";
cout<<endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  编程之美 查询