先从《编程之美》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