剑指offer28_数组中出现次数超过一半的数字

题目描述

数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。

解决:

如果只是统计数组中的元素个数的话,显然没有利用这个数组的特点
比较简单的一个思路是:这个数字不管是最小最大还是居中,都会是这个数组的中位数
所以最开始的解决思路是,对数组进行快速排序,然后返回中间一位的值
但是快速排序本身的复杂度就是NlogN了,显然不是最优


最后采用的思路:

利用partition()函数获得某一中间数字,其余数字按大小排在该数字的左右。
若该数字下标刚好为n/2,则该数字即为所求数字;
若小于n/2,则在右边部分继续查找;反之,左边部分查找(递归)

具体代码如下:
public class Solution {
        public int MoreThanHalfNum_Solution(int [] array) {
        if(array==null ||array.length<=0)
            return 0;
        int low=0;
        int high=array.length-1;
        int index=partition(array,low,high);//index也就是每次partition返回的中间数
        while(index!=array.length>>1){//右移一位等于除以2,效率更高
            if(index<array.length>>1){
                low=index+1;
                index=partition(array,low,high);//右递归
            }else{
                high=index-1;
                index=partition(array,low,high);//左递归
            }
        }
        //判断中位数出现的次数是否超过一半,如果没有超过一半则不存在要找的数字,则返回0
        int num=array[index];
        int times=0;
        for(int i=0;i<array.length;i++){
            if(array[i]==num){
                times++;
            }
        }
        if(times*2>array.length){
            return num;
        }
        return 0;
    }
    //partition函数是快速排序的基础,low最终与high汇合,返回值为前半部分的最后一位
    private int partition(int[] array,int low ,int high){
        int Key=array[low];
        while(low<high){
            while(low<high && array[high]>=Key){
                high--;
            }
            while(low<high && array[low]<=Key){
                low++;
            }
            if(low<high){
                int temp=array[low];
                array[low]=array[high];
                array[high]=temp;
            }
        }
        return low;
    }
}

猜你喜欢

转载自blog.csdn.net/lilililililydia/article/details/88928030