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

微软《编程之美》:寻找发贴“水王” 及 其扩展问题

2012-03-25 18:19 351 查看
原始问题

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

一种较好的思路:

如果每次删除两个不同的ID(不管是否包含“水王”的ID),那么,在剩下的ID列表中,“水王”ID出现的次数仍然超过总数的一半。看到这一点之后,就可以通过不断重复这个过程,把ID列表中的ID总数降低(转化为更小的问题),从而得到问题的答案,总的时间复杂度只有O(N),且只需要常数的额外内存。伪代码如下:

Type find(Type * ID, int N)
{
int nTimes = 0;
int i;
Type candidate;

for (i = 0; i < N; i++)
{
if (nTimes == 0)
{
candidate = ID[i];
nTimes++;
}
else
{
if (candidate == ID[i])
nTimes++;
else
nTimes--;
}
}

return candidate;
}


扩展问题:

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

 

思路:

先从2个人,每个人发贴数目都超过总数目的1/3开始考虑,思路和上面的思路是一样的,每次删除三个不一样的便可。只需增加一个nTimes2和一个candidate2便可,伪代码如下:

void Find(Type * ID, int N)
{
Type candidate1, candidate2;
int nTimes1 = 0, nTimes2 = 0;
int i;

for (i = 0; i < N; i++)
{
if(nTimes1 == 0)
{
if(ID[i] == candidate2)
nTimes2++;
else
{
candidate1 = ID[i];
nTimes1++;
}
}
else if (nTimes2 == 0)
{
if(ID[i] == candidate1)
nTimes1++;
else
{
candidate2 = ID[i];
nTimes2++;
}
}
else
{
if(ID[i] == candidate1)
nTimes1++;
else if(ID[i] == candidate2)
nTimes2++;
else
nTimes1--, nTimes2--;
}
}

printf("两个水王ID分别是:%d,%d\n", candidate1, candidate2);//假设ID类型为int
}

当“水王”数增加到3个时,思路还是一样,由上面程序再直接增加一个nTimes3和candidate3便可,伪代码如下:

void Find(Type * ID, int N)
{
Type candidate1, candidate2, candidate3;
int nTimes1 = 0, nTimes2 = 0, nTimes3 = 0;
int i;

for (i = 0; i < N; i++)
{
if(nTimes1 == 0)
{
if(ID[i] == candidate2)
nTimes2++;
else if (ID[i] == candidate3)
nTimes3++;
else
{
candidate1 = ID[i];
nTimes1++;
}
}
else if (nTimes2 == 0)
{
if(ID[i] == candidate1)
nTimes1++;
else if (ID[i] == candidate3)
nTimes3++;
else
{
candidate2 = ID[i];
nTimes2++;
}
}
else if (nTimes3 == 0)
{
if(ID[i] == candidate1)
nTimes1++;
else if (ID[i] == candidate2)
nTimes2++;
else
{
candidate3 = ID[i];
nTimes3++;
}
}
else
{
if(ID[i] == candidate1)
nTimes1++;
else if(ID[i] == candidate2)
nTimes2++;
else if(ID[i] == candidate3)
nTimes3++;
else
nTimes1--, nTimes2--, nTimes3--;
}
}

printf("三个水王ID分别是:%d,%d,%d\n", candidate1, candidate2, candidate3);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  扩展 微软 编程