数组中出现次数超过一半的数字(众数)

1. 转换为查找数组中第(length/2)小的值,可以利用快排中的partition进行交换排序。

在找到中位数之后,还需要统计中位数出现的次数,排除数组中根本没有众数的情况。

public static int partition(int[] array,int begin,int end,int k){
        if(begin==end) return array[begin];
        int length=end-begin+1;
        //采用随机枢纽提高效率
        Random ra=new Random();
        int position=Math.abs(ra.nextInt()%length)+begin;
        int key=array[position];
        int tmp=array[end];
        array[end]=array[position];
        array[position]=tmp;
        //开始一趟快排
        int i=begin,j=end;
        while(i<j){
            while(array[i]<=key&&i<j) i++;
            if(i<j) {
                array[j--]=array[i];
            }
            while(array[j]>key&&i<j) j--;
            if(i<j) {
                array[i++]=array[j];
            }
        }
        array[i]=key;
        if((i-begin+1)==k){
        //找到中位数,返回
            return array[i];
        }
        else if((i-begin+1)>k){
        //中位数在前半部分
            return partition(array,begin,i-1,k);
        }
        else{
        //中位数在后半部分
            return partition(array,i+1,end,k-(i-begin+1));
        }
    }
    public static int MoreThanHalfNum_Solution(int [] array) {
        if(array==null||array.length==0) return -1;
        int length=array.length;
        int candidate=partition(array,0,length-1,length/2);
        //统计候选众数的频数
        int count=0;
        for(int elem:array){
            if(elem==candidate) count++;
        }
        if(count>length/2) return candidate;
        return 0;
    }

2. 根据剑指offer提供的思路,可以利用数组的特点找出众数,具体思路如下:

a.若计数器pencil为0,则前面的数组已经完全抵消,记录下一个元素为候选众数,pencil置为1;

b.若pencil不为0,并且下一个元素与当前候选众数相等,pencil计数器加一;

c.若pencil不为0,并且下一个元素与当前候选众数不相等,pencil计数器减一。

最后保留的候选众数是经过若干抵消运算后留存下来的数字,通过遍历得到候选众数的实际数量,判断是否为众数。

    public static int MoreThanHalfNum_Solution(int [] array) {
        if(array==null||array.length==0) return -1;
        int length=array.length;
        int candidate=0;
        int pencil=0;//计数器
        for(int i=0;i<length;i++){
            if(pencil==0) {
                pencil=1;
                candidate=array[i];
            }
            else if(array[i]==candidate) {
                pencil+=1;
            }
            else if(array[i]!=candidate){
                pencil-=1;
            }
        }
        int count=0;
        for(int elem:array){
            if(elem==candidate) count++;
        }
        if(count>length/2) return candidate;
        return 0;
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值