寻找发帖“水王”

来源:编程之美2.3

题目:该"水王"发帖数目超过了帖子总数的一半。如果你有一个当前论坛上所有帖子(包括回帖)的列表,其中帖子作者的ID也在表中,你能快速找出这个传说中的Tango水王吗?
问题实质:寻找数组中出现的半数以上的数.
思路:如果每次删除两个不同的id,则剩下的水王id依然超过总数的一半,可以不断重复这个过程。

问题扩展:如果有3个id,发贴总数都超过了帖子总数的四个之一,如果快速找到他们。思路都差不多。

/*题目:该"水王"发帖数目超过了帖子总数的一半。如果你有一个当前论坛上所有帖子(包括回帖)的列表,
 其中帖子作者的ID也在表中,你能快速找出这个传说中的Tango水王吗?
问题实质:寻找数组中出现的半数以上的数. 
拓展:有3个数,他们的出现次数都超过了总数的1/4.
*/
public class ShuiWang2_3 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
	 int[] id = { 1, 1, 1, 5, 1, 1, 1, 3, 1, 7, 1, 3, 1, 2, 1, 1, 4, 56, 1, 12, 4, 1, 3, 4,
			        1, 1, 1, 3, 1, 1, 1, 5, 1, 1, 3, 12, 1, 2, 1, 2, 2, 2, 2, 2,2 };

	 System.out.println(MoreHalfNum(id,id.length));

	 int id2[] = {5, 5, 5, 7, 7, 8, 8, 8, 8, 2,
             2, 2, 2, 2, 2, 2, 2, 5, 5, 5, 
    6, 5, 6, 7, 7, 7, 7, 7, 7, 7,
             7, 5, 7, 2, 2, 2, 5, 5, 5, 8};
	 printArr(findMore(id2));
	}

	//每次从数组中删除两个不同的数,不断重复这个过程
	//算法中当然不是真的删除数,而是用一个计数器巧妙的实现“删除”
	public static int MoreHalfNum(int data[],int n)
	{
		int candidate=0;//候选值
		int nTime=0;//候选值出现的次数
		for(int i=0;i<n;i++){			
			if(nTime==0)//nTime为0时说明需要重新立候选值
				{
				candidate=data[i];
				nTime++;
			}else{
				if(data[i]==candidate)nTime++;//又出现了,权值加1
				else nTime--;//不等,权值减1
			}
		}
		
	  return candidate;
	}
	
	public static int[] findMore(int[] data){
		int[] res=new int[3];//数组,存出现次数最多的三个数
		int[] nTimes={0,0,0};//数组,存每个候选值出现的次数		
		int i;	
		
		for(i=0;i<data.length;i++){
			int index;
			//1.如果存在某个index,使得nTimes[index]==0,则重新赋候选值
			for(index=0;index<3;index++){
				if(nTimes[index]==0){
					res[index]=data[i];
					nTimes[index]++;
					break;
				}
			}
			if(index<3)continue;
			//2.如果存在index,满足res[index]=id[i]),则对应权值加1
			for(index=0;index<3;index++){
				if(res[index]==data[i]){					
					nTimes[index]++;
					break;
				}
			}
			if(index<3)continue;
			//3.其它情况,对应权值都减1
			for(index=0;index<3;index++){									
				nTimes[index]--;				
			}		
		}		
		return res;
	}
	
	private static void printArr(int[] a){
		for(int s:a){
			System.out.print(s+" ");
		}
	}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值