Day31: 数组中出现次数超过一半的数字

146 阅读2分钟

描述

给一个长度为 n 的数组,数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。

例如输入一个长度为9的数组[1,2,3,2,2,2,5,4,2]。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。

数据范围:�≤50000n≤50000,数组中元素的值 0≤���≤100000≤val≤10000

要求:空间复杂度:�(1)O(1),时间复杂度 �(�)O(n)

题源:数组中出现次数超过一半的数字_牛客题霸_牛客网 (nowcoder.com)

输入描述:

保证数组输入非空,且保证有解

示例1

输入:

[1,2,3,2,2,2,5,4,2]

复制

返回值:

2

复制

示例2

输入:

[3,3,3,3,2,2,2]

复制

返回值:

3

复制

示例3

输入:

[1]

复制

返回值:

1

知识点:哈希表

哈希表是一种根据关键码(key)直接访问值(value)的一种数据结构。而这种直接访问意味着只要知道key就能在�(1)O(1)时间内得到value,因此哈希表常用来统计频率、快速检验某个元素是否出现过等。

思路:

首先我们分析一下,数组某个元素出现次数超过了数组长度的一半,那它肯定出现最多,而且只要超过了一半,其他数字不可能超过一半了,必定是它。

如果给定的数组是有序的,那我们在连续的相同数字中找到出现次数最多即可,但是题目没有要求有序,一种方法是对数组排序后解决,但是时间复杂度就上去了。那我们可以考虑遍历一次数组统计各个元素出现的次数,找到出现次数大于数组长度一半的那个数字。

具体做法:

  • step 1:构建一个哈希表,统计数组元素各自出现了多少次,即key值为数组元素,value值为其出现次数。
  • step 2:遍历数组,每遇到一个元素就把哈希表中相应key值的value值加1,用来统计出现次数。
  • step 3:本来可以统计完了之后统一遍历哈希表找到频次大于数组长度一半的key值,但是根据我们上面加粗的点,只要它出现超过了一半,不管后面还有没有,必定就是这个元素了,因此每次统计后,我们都可以检查value值是否大于数组长度的一半,如果大于则找到了。
public int MoreThanHalfNum_Solution(int [] array) {
    HashMap<Integer,Integer>map = new HashMap();
    for (int i = 0;i < array.length;i++){
        if (!map.containsKey(array[i])){
            map.put(array[i],1);
        }else {
            map.put(array[i],map.get(array[i])+1);
        }
        if (map.get(array[i]) > (array.length >> 1)){
            return array[i];
        }
    }
    return 0;
}
  • 时间复杂度:O(n),遍历一次数组,哈希表每次操作的复杂度都是O(1)
  • 空间复杂度:O(n)