1.寻找发帖水王
《编程之美》一书上关于发帖水王的解答请参见点击打开链接。但是该算法求解的答案并不符合题意,当前求解的答案只是候选者,绝不是真正的发帖水王。比如,输入:{1,2,3,4,5,6,7,87,8,9,10,11,11},输出:11.此时很直观可以确认id=11的作者不是发帖水王。书上给出的算法求解的只是候选者后,应再进行一遍遍历计数,确定个数确实大于总个数的一半,才能被认为是发帖水王。
2.求解发帖水王
// 找到超过n/2项的众数
public int findKing(int[] ids) {
if(ids==null || ids.length<1) return -1;
int candidate = ids[0],nTime = 1;
for(int i=1;i<ids.length;i++) {
if(nTime == 0) {
candidate = ids[i];
nTime = 1;
}else {
if(candidate == ids[i]) nTime++;
else nTime--;
}
}
// 遍历计数
nTime = 0;
for(int i=0;i<ids.length;i++)
if(candidate==ids[i])
nTime++;
if(nTime>ids.length/2) return candidate;
else return -1;
}
3.求解发帖水王的拓展问题
// 找到三个id的发帖数量都超过n/4项的众数集合
public void findKings(int[] ids) {
if(ids==null ||ids.length<3) return;
int[] candidate = {-1,-1,-1};
int[] nTime = {0,0,0};
for(int i=0;i<ids.length;i++) {
boolean flag = false;
for(int j=0;j<3;j++)
if(ids[i] == candidate[j]) {
nTime[j]++;
flag = true;
break;
}
if(!flag) {// 表示当前不存在
for(int t=0;t<3;t++) {
if(nTime[t] == 0) {
candidate[t] = ids[i];
nTime[t] = 1;
flag = true;
break;
}
}
if(!flag) {
for(int k = 0;k<3;k++)
nTime[k] --;
}
}
}
int[] count = {0,0,0};
for(int i=0;i<3;i++)//保证找到3个候选者
if(nTime[i]<1) {
System.out.println("不存在");
return;
}
for(int i=0;i<ids.length;i++)
for(int j=0;j<3;j++)
if(ids[i] == candidate[j]) {
count[j]++;
break;
}
if(count[0]>ids.length/4&&count[1]>ids.length/4&&count[2]>ids.length/4)
System.out.println(candidate[0]+"\t"+candidate[1]+"\t"+candidate[2]);
else
System.out.println("不存在");
}