数据结构练习(35)数组中出现次数超过一半的数字
http://zhedahht.blog.163.com/blog/static/25411174201085114733349/
思路:
编程之美上面的一道题“寻找水王”。百度电话面试的时候也恰巧问到,当时比较紧张,怎么也想不出来。
其实我觉得这种类似于智力题的题目还是需要一定的积累的,再聪明的人如果没有经过一定的训练也很难想出来解法。
《编程珠玑》上面提到过“最大子段和”问题,现在看起来十分简单,那是因为自己反复训练过,如果看到这个最优解的获取过程,
还是十分艰辛的,是很多人经过很长时间才弄出来的一个问题。
#include <iostream> using namespace std; bool SolveProblem(int n[], int len, int& x) { if (n == nullptr || len <= 0) return false; int times = 0; int result; for (int i = 0; i < len; ++i) { if (times == 0) result = n[i], ++times; else if (result == n[i]) ++times; else if (result != n[i]) --times; } times = 0; for (int i = 0; i < len; ++i) if (result == n[i]) ++times; if (times * 2 > len) { x = result; return true; } else return false; } int main() { int n[] = {1, 2, 1, 3, 1, 4, 1}; int result; if (SolveProblem(n, 7, result)) cout << result << endl; else cout << "failed to find" << endl; return 0; }
变型1:
随着Tango的发展,管理员发现,“超级水王”没有了。统计结果表明,有3个发帖很多的ID,他们的发帖数目都超过了帖子总数目N的1/4。你能从发帖ID列表中快速找出他们的ID吗?
bool SolveProblemHarder(int n[], int len, int& x, int& y, int& z) { if (n == nullptr || len <= 0) return false; int times[3]; int candidate[3]; times[0] = times[1] = times[2] = 0; for (int i = 0; i < len; ++i) { if (times[0] == 0) candidate[0] = n[i], ++times[0]; else if (times[1] == 0) candidate[1] = n[i], ++times[1]; else if (times[2] == 0) candidate[2] = n[i], ++times[2]; else if (candidate[0] == n[i]) ++times[0]; else if (candidate[1] == n[i]) ++times[1]; else if (candidate[2] == n[i]) ++times[2]; else --times[1], --times[2], --times[3]; } x = candidate[0], y = candidate[1], z = candidate[2]; return true; }
变型2:
如果这个数字恰好出现为一半应该如何解决?
思路:
拿掉2个不相同的数字,按照第一种方法求出来result,如果满足条件则返回,如果不满足则拿掉的2个数字中必有一个,然后稍加判断问题解决。
-------------------------------------------------------
kedebug
Department of Computer Science and Engineering,
Shanghai Jiao Tong University
E-mail: kedebug0@gmail.com
GitHub: http://github.com/kedebug
-------------------------------------------------------