题目描述

数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组[1,2,3,2,2,2,5,4,2]。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。你可以假设数组是非空的,并且给定的数组总是存在多数元素。1<=数组长度<=50000
示例1
输入:[1,2,3,2,2,2,5,4,2]
返回值:2

题目分析

因为数组长度(length)是确定的,可以计算出数组长度的一半(length/2)是多少,直观的想,可以遍历数组,统计数字出现的次数,若是不小于length/2,即目标数字。

解题思路

方法1:使用hashMap,保存数字数值和出现次数,若是重复出现则将次数加1;
图片说明
遍历最后结果
图片说明
方法2:对数组排序,位于数组的中间下标的数字,就是目标数字;
排序后数组显示:
图片说明

代码实现

方法一:哈希法

 public int MoreThanHalfNum_Solution(int [] array) {
        if(array == null || array.length == 0) return 0;
        if(array.length == 1) return array[0];
        // hashmap存储数字和它的出现次数
        HashMap<Integer,Integer> map = new HashMap<Integer,Integer>();
        for(int i=0;i<array.length;i++){
            // 若map中没有,则放入hashmap,并将次数置为1
            if(!map.containsKey(array[i])){
                map.put(array[i],1);
            }else if(map.get(array[i]) < array.length/2){
                // 若map中有,且次数少于一半,就将map中的次数加1
                map.put(array[i],map.get(array[i])+1);
            }else{
                // 若map中有,且次数多于或等于一半,则直接返回该数
                return array[i];
            }
        }
        return 0;
    }

时间复杂度:O(n),其中 n 是数组 array 的长度。遍历数组 array 一次,对于 array 中的每一个元素,获取哈希表中的值以及将其插入哈希表都只需要常数时间,因此时间复杂度为 O(n)。
空间复杂度:O(n),哈希表最多存储 n/2 个数据,因此空间复杂度为 O(n)。

方法二:数组排序

 public int MoreThanHalfNum_Solution(int [] array) {
        if(array == null || array.length == 0) return 0;
        if(array.length == 1) return array[0];
        // 快速排序
        Arrays.sort(array);
        // 返回数组的中间值
        return array[array.length/2];
}

时间复杂度:因为使用了Arrays.sort()方法,实现的是快速排序,所以时间复杂度为O(nlogn),相比哈希法要消耗更多的时间。
空间复杂度:若是题目明确要求不能改变原来的数组,则需要创建一个新的与原来的数组一样的数组,空间复杂度O(n),若是没有要求,则可以直接在原来的数组上修改,空间复杂度O(1)。