问题:
Tango是微软亚洲研究院的一个试验项目。研究院的员工和实习生们都很喜欢在Tango上面交流灌水。传说,Tango有一大“水王”,他不但喜欢发贴,还会回复其他ID发的每个帖子。坊间风闻该“水王”发帖数目超过了帖子总数的一半。如果你有一个当前论坛上所有帖子(包括回帖)的列表,其中帖子作者的ID也在表中,你能快速找出这个传说中的Tango水王吗?
思路:
已知水王发帖子数量超过半,在遍历id过程中,遇见不同的id就相互消除,那么水王的发帖子数目始终就是当前帖子总数的一半多。当排除到最后的时候就只剩下水王了。
具体实现的设计思路:
设置两个参数(1)candidate就是处理过的帖子中最后面的一个
(2)nTime就是处理过但是还没有被抵消的有多少个帖子
如果剩余的为0那么就如果目前处理过还没有被抵消的帖子数量为0,那么将此时正要处理的帖子设置为candidate,并且更新nTime
否则进行判断此时正要处理的帖子和之前处理过的帖子中最后面的一个比较,如果相同就让nTime+1
否则相消nTime-1
最终剩下的肯定都是水王的,并且时间复杂度最小为O(N)。
序号 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
id | 水 | a | 水 | b | 水 | 水 | a | b | b | 水 | 水 |
candidate | 水 | 水 | 水 | 水 | 水 | 水 | 水 | 水 | b | b | 水 |
nTime | 0 | 1 | 0 | 1 | 0 | 1 | 2 | 1 | 0 | 1 | 0 |
源程序代码:此处只贴出了实现用的函数体,需要输入含有用户id的String数组,还有帖子总数。
1 String Find(String* ID, int N) 2 { 3 String candidate; //candidate就是处理过的帖子中最后面的一个 4 int nTimes, i; //nTime就是处理过但是还没有被抵消的有多少个帖子 5 for(i = nTimes = 0; i < N; i++) 6 { 7 if(nTimes == 0) //如果目前处理过还没有被抵消的帖子数量为0,那么将此时正要处理的帖子设置为candidate,并且更新nTime
8 { 9 candidate = ID[i], nTimes = 1; 10 } 11 else 12 { 13 if(candidate == ID[i]) //如果相同那么就有就增加一次相抵消的机会 14 nTimes++; 15 else //不同就跳过就是抵消,就是减少剩余帖子数量 16 nTimes--; 17 18 } 19 20 } 21 return candidate; 22 }