微软《编程之美》:寻找发贴“水王” 及 其扩展问题
2012-03-25 18:19
351 查看
原始问题
Tango是微软亚洲研究院的一个试验项目。研究院的员工和实习生们都很喜欢在Tango上面交流灌水。传说,Tango有一大“水王”,他不但喜欢发贴,还会回复其他ID发的每个帖子。坊间风闻该“水王”发帖数目超过了帖子总数的一半。如果你有一个当前论坛上所有帖子(包括回帖)的列表,其中帖子作者的ID也在表中,你能快速找出这个传说中的Tango水王吗?
一种较好的思路:
如果每次删除两个不同的ID(不管是否包含“水王”的ID),那么,在剩下的ID列表中,“水王”ID出现的次数仍然超过总数的一半。看到这一点之后,就可以通过不断重复这个过程,把ID列表中的ID总数降低(转化为更小的问题),从而得到问题的答案,总的时间复杂度只有O(N),且只需要常数的额外内存。伪代码如下:
扩展问题:
随着Tango的发展,管理员发现,“超级水王”没有了。统计结果表明,有3个发帖很多的ID,他们的发帖数目都超过了帖子总数目N的1/4。你能从发帖ID列表中快速找出他们的ID吗?
思路:
先从2个人,每个人发贴数目都超过总数目的1/3开始考虑,思路和上面的思路是一样的,每次删除三个不一样的便可。只需增加一个nTimes2和一个candidate2便可,伪代码如下:
当“水王”数增加到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);
}
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);
}
相关文章推荐
- 《编程之美》: 寻找发帖水王的扩展问题 2.3
- 《编程之美》读书笔记: 寻找发帖水王的扩展问题 2.3
- 编程之美2.12快速寻找满足条件的两个数及扩展问题Java版
- 编程之美2.3寻找发帖水王扩展问题
- 编程之美2.3寻找发帖水王和扩展问题
- 编程之美2.10寻找数组中的最大值和最小值扩展问题Java版
- 《编程之美》寻找发帖水王扩展问题的代码实现
- 编程之美寻找数组中的最大值和最小值以及扩展问题
- 编程之美1.3 一摞烙饼的排序(扩展问题)
- 编程之美 2.3 寻找发帖水王扩展问题
- 《编程之美》读书笔记(八):“发帖水王”扩展问题
- 《编程之美》读书笔记(十二):“求数组的子数组之和的最大值”扩展问题
- 《编程之美》3.11 扩展问题
- 编程之美4.4点是否在三角形内扩展问题
- 寻找发帖水王扩展问题
- 编程之美2.14扩展问题1 求子数组和的最大值(首尾可以相连)
- 寻找发帖水王 扩展问题
- 寻找发帖“水王”的扩展问题
- 编程之美2.10扩展问题求数组中第二大数
- 编程之美4.1扩展问题