【算法】数组中出现次数超过一半的数字

题目描述:

数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。

例如{2,1,3,2,2,2,2,5,4,2,2,2,2},由于数字2的个数超过了数组长度的一半,则输出2.


解题思路1:

数组排序后有一个特征:数组中如果有超过一半长度的数字,则排序之后位于数组中间的数字一定是超过一半的数字。也就是中位数。受快速排序的启发,随即找出一个数字,如果其最终位置位于n/2,则这个数字就是中位数。如果最终位置大于n/2,则中位数一定位于其左边,递归查找其左边。如果最终位置小于n/2,则位于数组右边,递归查找右边。

解题思路2:

数组中如果有超过一半长度的数字,则它出现的次数比其他所有数字的出现的总次数都要多。因此,遍历时保存两个值,一个是数组中的数字,一个是出现次数。当遍历到下一个数字时,如果下一个数字和当前数字相同则times++,如果和下一个数字不同,则times--;如果次数为0,则重新保存下一个数字并将times置为1.如果存在次数超过一半,最后一次置为1的数字,一定是出现次数超过一半的数字。


public class Main {

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
        String a=in.nextLine();
        String b[]=a.split(" ");
        int temp[]=new int[b.length];
        for(int i=0;i<b.length;i++){
        	temp[i]=Integer.valueOf(b[i]);
        }
        System.out.println(MoreThanHalf(temp,b.length));
        System.out.println(MoreThanHalf2(temp,b.length));
        
	}
	static int MoreThanHalf(int a[],int length){
		int middle=length/2;
		int star=0;
		int end=length-1;
		int index=partition(a,star,end);
		while(index!=middle){
			if(index>middle){
				end=index-1;
				index=partition(a,star,end);
			}
			else{
				star=index+1;
				index=partition(a,star,end);
			}
		}
		
		int times=0;
		int result=a[middle];
		for(int i=0;i<length;i++){//判断是否超过一半
			if(a[i]==result)
				times++;
		}
		if(times*2<=length)
			return -1;
		
		return result;
	}
	public static int partition(int[] a, int low, int high){  
        
        int key = a[low];//基准元素,排序中会空出来一个位置  
        while(low<high){  
            while(low<high && a[high]>=key){//从high开始找比基准小的,与low换位置  
                high--;  
            }  
            a[low]=a[high];  
            while(low<high && a[low]<=key){//从low开始找比基准大,放到之前high空出来的位置上  
                low++;  
            }  
            a[high]=a[low];  
        }  
        a[low]=key;//此时low=high 是基准元素的位置,也是空出来的那个位置  
        return low;  
        
    } 
}


 

解题思路2代码:

static int MoreThanHalf2(int a[],int length){
		
		int result=a[0];
		int times=1;
		for(int i=1;i<length;i++){
			if(times==0){
				result=a[i];
				times=1;
			}
			else if(a[i]==result)
				times++;
			else times--;
		}
		int t=0;
		
		for(int i=0;i<length;i++){//判断是否超过一半
			if(a[i]==result)
				t++;
		}
		if(t*2<=length)
			return -1;
		
		return result;
	}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值