partition3.找到数量超过一半的数字

找到数量超过一半的数字

如果没有返回0.
统计一个数字出现的次数,最简单的想到的就是排序,排序算法的复杂度为O(logn)。
所以这个题肯定是根据数组本身特点来做,一个数超过一半,则说明排好序之后这个数一定在数组中间。
出现的次数比其他数字出现的次数加起来还要多。
所以设置两个变量,一个保存数字,一个保存次数。遍历时,**如果它与之前的数字相同则次数加1,不相同则次数减1.若次数为0,则保存下一个数字并将次数变为1.**这样的话遍历完之后这个数字一定是出现最多的。

public class Solution {
    public int MoreThanHalfNum_Solution(int [] array) {
        if(array==null || array.length==0){
            return 0;
        }
        int time=1;
        int num=array[0];
        for(int i=1;i<array.length;i++){
            if(time==0){
                time++;
                num=array[i];
            }else{
                if(array[i]==num){
                    time++;
                }else{
                    time--;
                }
            }
        }
        time=0;
        for(int i=0;i<array.length;i++){
            if(array[i]==num){
                time++;
            }
        }
        return time>array.length>>1?num:0;
    }
}

第二种做法就是基于partition做法,这个题其实就是把排序好的数组分成两半的话,中位数肯定是这个数(如果存在超过一半的数)
首先对一个数组的全部进行partition,得到其中一个随机数左边比他小右边比它大的数组的下标数组,如果这个下标下限大于mid,说明这个超过一半的数在左边,如果下标小于mid,说明在右边,循环partition,直到这个数的下标在中间,则这个数就可能是那个数了,再检查这个数的个数是否超过一半,如果超过则返回这个数,没有超过则返回0
partition就是首先选一个随机数,然后遍历数组,把比它小的数放到左边,把比它大的放到右边和它一样大的放中间。partition完之后,返回等于它的最小最大的坐标。这样的复杂度是O(n)。

public class Solution {
    public int MoreThanHalfNum_Solution(int [] array) {
        if(array==null || array.length==0){
            return 0;
        }
        int mid=array.length>>1;
        int lo=0;
        int hi=array.length-1;
        int[] s=partition(array,lo,hi);
        while(s[0]>mid || s[1]<mid){
            if(s[0]>mid){
                hi=s[0]-1;
                s=partition(array,lo,hi);
            }else{
                lo=s[1]+1;
                s=partition(array,lo,hi);
            }
        }
        int time=0;
        for(int i=0;i<array.length;i++){
            if(array[i]==array[s[0]]){
                time++;
            }
        }
        return time>mid?array[s[0]]:0;
    }
    public int[] partition(int [] arr,int lo,int hi){
        int ran=lo+(int)(Math.random()*(hi-lo+1));
        swap(arr,ran,hi);
        int cur=lo;
        int less=lo-1;
        int more=hi;
        while(cur<more){
            if(arr[cur]<arr[hi]){
                swap(arr,++less,cur++);
            }else if(arr[cur]>arr[hi]){
                swap(arr,--more,cur);
            }else{
               cur++;
            }
        }
        swap(arr,more++,hi);
        return new int[]{less+1,more-1};
    }
    public void swap(int[] arr,int i,int j){
        int temp=arr[i];
        arr[i]=arr[j];
        arr[j]=temp;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值