先从《编程之美》2.3节“寻找发帖水王”问题说起。
【问题】数组中某个数出现次数超过1/2,求该数。
【思路】遍历数组,只要当前的数同临时变量candidate相同,则计数加1,不相同则计数减1,一旦计数为0则临时变量candidate更换成当前的数,继续上述规则。由于某个数出现次数大于一半,则最后临时变量一定保存了该数。
/*查找数组中出现一半的数*/ public static int find(int[] candidates) { int candidate=0,time=0; for (int i = 0; i < candidates.length; i++) { if (time==0) { candidate=candidates[i]; time=1; }else { if (candidate==candidates[i]) { time++; }else { time--; } } } return candidate; }
**************************************************************************
【扩展题目】《编程之美》的扩展问题,三个数在数组中出现的次数都超过1/4,求这三个数。
【思路】:假设是A、B、C超过了1/4,剩下的数的集合记为D,则所以的A与D相比是超过了A+D的一半,所有的B与D相比是超过了B+D的一半,所有的C与D相比是超过了C+D的一半。转化为上述问题求解。
/*查找数组中三个出现次数超过1/4的数*/ public static int[] overQuarter(int[] candidates) { int[] result=new int[3]; int[] times=new int[3]; for (int i = 0; i < candidates.length; i++) { if (times[0]==0) { times[0]=1; result[0]=candidates[i]; }else if (times[1]==0) { times[1]=1; result[1]=candidates[i]; }else if (times[2]==0) { times[2]=1; result[2]=candidates[i]; }else if (candidates[i]==result[0]) { times[0]++; }else if (candidates[i]==result[1]) { times[1]++; }else if (candidates[i]==result[2]) { times[2]++; }else { times[0]--; times[1]--; times[2]--; } } return result; }
*****************************************************************
【再次扩展】推而广之,2个数出现的次数超过1/3,4个数出现的次数超过1/5……,n个数出现的次数超过1/(n+1),都可以用上面思路求得。
原文地址:http://blog.csdn.net/brillianteagle/article/details/39853081