寻找发帖“水王”
Tango 是微软亚洲研究院的一个试验项目。研究院的员工和实习生们都很喜欢在Tango上面交流灌水。传说,Tango 有一大“水王”,他不但喜欢发贴,还会回复其他ID 发的每个帖子。坊间风闻该“水王”发帖数目超过了帖子总数的一半。如果你有一个当前论坛上所有帖子(包括回帖)的列表,其中帖子作者的ID 也在表中,你能快速找出这个传说中的Tango 水王吗?
分析:
如果每次删除两个不同的 ID(不管是否包含“水王”的ID),那么,在剩下的ID 列表中,“水王”ID 出现的次数仍然超过总数的一半。看到这一点之后,就可以通过不断重复这个过程,把ID 列表中的ID 总数降低(转化为更小的问题),从而得到问题的答案。该思路,避免了排序这个耗时的步骤,总的时间复杂度只有O(N),且只需要常数的额外内存。
代码:
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; }
扩展问题:
如果有3个人的发帖数量都超过1/4.怎么把他们三个都找到.
代码:
Type candidate1; Type candidate2; Type candidate3; void Find(Type* ID, int N) { int nTimes1 = 0; int nTimes2 = 0; int nTimes3 = 0; for(int i = 0; i < N; i++) { if (nTimes1 == 0) { candidate1 = ID[i]; nTimes1 = 1; } else if (nTimes2 == 0) { candidate2 = ID[i]; nTimes2 = 1; } else if (nTimes3 == 0) { candidate3 = ID[i]; nTimes3 = 1; } else if (nTimes4 == 0) { candidate4 = ID[i]; nTimes4 = 1; } else { if (candidate1 == ID[i]) nTimes1++; else if (candidate2 == ID[i]) nTimes2++; else if (candidate3 == ID[i]) nTimes3++; else if (candidate4 == ID[i]) nTimes4++; else { nTimes1--; nTimes2--; nTimes3--; } } } } int main() { int a[] = {0,4,1,4,0,4,1,4,1,0,3,3,0,3,3,3}; Find(a,16); cout << candidate1 <<" " << candidate2 << " " << candidate3 << endl; return 0; }
浙公网安备 33010602011771号