剑指offer 29题 【时间效率】数组中出现次数超过一半的数字

题目描述

数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
牛客传送门:点击打开链接
写一个鲁棒的代码还是不容易的...
思路:
1.不断地利用partition函数进行分割,结束条件为partition返回的index 是数组长度的一半。因为我们寻找的这个数字超过一半,所以中间的这个数就是要寻找的。
2.假设这个数字是第一个,并计数1。那么遍历数组,如果遇到相同的数字,则计数加一,否则减一,当计数小于0时把当前数字假设为我们所求的数,并重新计数。最后检查这个数字是否是超过一半的。
代码一:
public class Title29 {
    public int MoreThanHalfNum_Solution(int [] array) {
        if(array == null || array.length == 0)
            return 0;
        int begin = 0,end = array.length-1,index = -1;;

        int mid = (begin + end) >>> 1;
        while(index != mid){
            index = partition(array,begin,end);
            if(index > mid){
                end = index - 1;
            }else{
                begin = index + 1;
            }
        }
        if(checkHalf(array, array[index]))
            return array[index];
        return 0;
    }

    public int partition(int[] array,int begin,int end){
        int pos = selectNumber(array,begin,end);
        swap(array,pos,end);
        
        int small = begin -1;
        for(int i=begin;i<end;i++){
            if(array[i] < array[end]){
                ++small;
                if(i != small){
                    swap(array,i,small);
                }
            }
        }
        
        ++small;
        swap(array,small,end);
        return small;
    }

    // 三数取中
    public int selectNumber(int[] array,int begin,int end){
        if(end-begin>1){
            int mid = (end+begin) >> 1;
            int max = begin;
            
            // 获取最大的位置
            if(array[max] < array[mid])
                max = mid;
            if(array[max] < array[end])
                max = end;
            
            // 
            if(max == begin){
                return array[mid] > array[end] ? mid : end;
            }else if(max == mid){
                return array[begin] > array[end] ? begin : end;
            }else{
                return array[begin] > array[mid] ? begin : mid;
            }
        }
        return begin;
    }
    
    public void swap(int[] array,int posA,int posB){
        int temp = array[posA];
        array[posA] = array[posB];
        array[posB] = temp;
    }
    
    public boolean checkHalf(int[] array,int num){
        int count = 0;
        for(int i=0;i<array.length;i++){
            if(array[i] == num)
                count ++;
        }
        if(count > (array.length >>>1))
            return true;
        return false;
    }

    public static void main(String[] args) {
        //int[] a = {1,2,3,2,2,2,5,4,2};
       // new Title29().MoreThanHalfNum_Solution(a);
        //int[] b = {1,2,3,2,4,2,5,2,3};
        //new Title29().MoreThanHalfNum_Solution(b);
        int[] c = {2,2,2,2,2,1,3,4,5};
        System.out.println(new Title29().MoreThanHalfNum_Solution(c));
    }
}

代码二:
public class Title29 {
    public int MoreThanHalfNum_Solution(int [] array) {
        if(array == null || array.length == 0)
            return 0;
        
        int num=array[0],count = 0;
        for(int i=1;i<array.length;i++){
            if(array[i] == num)
                count++;
            else{
                count--;
                if(count<0){
                    num = array[i];
                    count = 0;
                }
            }
        }
        
        if(checkHalf(array, num))
            return num;
        return 0;
    }
    
    public boolean checkHalf(int[] array,int num){
        int count = 0;
        for(int i=0;i<array.length;i++){
            if(array[i] == num)
                count ++;
        }
        if(count > (array.length >>>1))
            return true;
        return false;
    }

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章