这道题的关键是统计数组中每个数字的出现次数。
第一反应也许会想到再开一个新的数组来统计,但实际上这样做并不合适,因为数组中的数字是离散的,一方面,我们并不知道数字的范围,另一方面,使用普通的数组来统计会造成大量的空间浪费。就这道题来说,比较合适的数据结构是HashMap,HashMap的键对应的是数组中的数字,而HashMap的值对应的是数组中数字对应的出现次数。
既然要找到占比超过一半的数,我们就得知道数字总数,也就是数组的长度:
int len = array.length;
然后就枚举数组中的每一个数num,更新每个数字的出现次数,也就是HashMap里键和值的映射关系。我们很自然可以想到用HashMap中的put函数来实现这个目的。put函数有两个参数key和value,key很显然就是我们枚举的数字num,value则是num的出现次数,那如何来表示num的出现次数呢?
直觉上我们可以用HashMap中的get函数,这个函数可以返回指定键所映射的值,但是有一个特殊情况,如果HashMap中尚未存在该键所对应的映射关系,get函数就会返回null值,对应这道题目,也就是在枚举到一个第一次出现的数num时,HashMap还没有存储num所对应的映射关系。由于这样的情况存在,如果我们要使用get函数来获取数字的出现次数,还需要用if-else来专门处理num第一次出现的情况。
不过,Java 8中引入了一个简洁的处理上述情况的方式,也就是getOrDefault函数,和get函数相比,getOrDefault函数多了一个参数defaultValue,也就是当HashMap中不存在某个键所对应的映射关系时,会默认返回的值,在这道题当中是0,也就是当某个数num第一次出现之前,num的出现次数为0。这样,我们就能比较简洁地来更新HashMap中的映射关系了。
numCnt.put(num, numCnt.getOrDefault(num, 0) + 1);
一轮for循环过后,我们就获取了每个数字的出现次数。我们再通过一轮for循环枚举数组中的每个数组num,通过HashMap的get函数来获取num的出现次数,如果num的出现次数超过了数字总数的一半,就返回num。
完整代码如下:
public static int solution(int[] array) {
// Edit your code here
Map<Integer,Integer> numCnt = new HashMap<>();
int len = array.length;
for(int num : array) {
numCnt.put(num, numCnt.getOrDefault(num, 0) + 1);
}
for(int num : array) {
int count = numCnt.get(num);
if(count > len / 2) {
return num;
}
}
return 0;
}