Tango是微软亚洲研究院的一个试验项目。研究院的员工和实习生们都很喜欢在Tango上面交流灌水。传说,Tango有一大"水王",他不但喜欢发帖,还会回复其他ID发的每个帖子。坊间风闻该"水王"发帖数目超过了帖子总数的一半。如果你有一个当前论坛上所有帖子(包括回帖)的列表,其中帖子作者的ID也在表中,你能快速找出这个传说中的Tango水王吗?
方法一:暴力求解
对每一个ID,遍历整个列表,统计出现的次数,如果超过一半,则说明找到了"水王"。复杂度O(n2)。
参考代码如下:
1 int find(vector<int> id) 2 { 3 int ret = -1; 4 int len = id.size(); 5 int cnt = len/2; 6 for (int i = 0; i <= cnt; i++) 7 { 8 int cnti = 1; 9 for (int j = i+1; j < len; j++) 10 if (id[j] == id[i]) cnti++; 11 if (cnti > cnt) 12 { 13 ret = id[i]; 14 break; 15 } 16 } 17 return ret; 18 }
方法二:排序
先对所有ID排序。如果某个ID出现的次数超过总数的一半,那么,这个有序的ID列表中的第N/2项一定这个ID。复杂度O(nlogn)。
参考代码如下:
1 int find(vector<int> id) 2 { 3 sort(id.begin(), id.end()); 4 return id[id.size()/2]; 5 }
方法三:线性时间算法
如果每次删除两个不同的ID,那么,在剩下的ID列表中,"水王"ID出现的次数仍然超过总数的一半。可以通过不断重复这个过程,把ID列表中的ID总数降低,从而得到答案。参考代码如下所示:
1 int find(vector<int> id) 2 { 3 int ret, len = id.size(); 4 for (int i = 0, n = 0; i < len; i++) 5 { 6 if (n == 0) 7 { 8 ret = id[i]; 9 n++; 10 } 11 else 12 { 13 if (ret == id[i]) n++; 14 else n--; 15 } 16 } 17 return ret; 18 }
扩展问题
随着Tango的发展,管理员发现,"超级水王"没有了。统计结果表明,有3个发帖很多的ID,他们的发帖数目都超过了帖子总数的1/4。你能从发帖ID列表中快速找出他们的ID吗?
【解答】参考代码如下:
1 vector<int> find(vector<int> id) 2 { 3 vector<int> ret(3, -1); 4 5 int n0 = 0, n1 = 0, n2 = 0, len = id.size(); 6 for (int i = 0; i < len; i++) 7 { 8 if (id[i] == ret[0]) n0++; 9 else if (id[i] == ret[1]) n1++; 10 else if (id[i] == ret[2]) n2++; 11 else if (n0 == 0) 12 { 13 n0 = 1; 14 ret[0] = id[i]; 15 } 16 else if (n1 == 0) 17 { 18 n1 = 1; 19 ret[1] = id[i]; 20 } 21 else if (n2 == 0) 22 { 23 n2 = 1; 24 ret[2] = id[i]; 25 } 26 else 27 { 28 n0--; 29 n1--; 30 n2--; 31 } 32 } 33 return ret; 34 }
时间: 2024-10-10 20:32:44