题目描述:
给一个长度为 n 的数组,数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
例如输入一个长度为9的数组[1,2,3,2,2,2,5,4,2]。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。
数据范围:n≤50000,数组中元素的值0≤val≤10000
要求:空间复杂度:O(1),时间复杂度O(n)
输入描述:
保证数组输入非空,且保证有解
示例1:
输入:[1,2,3,2,2,2,5,4,2]
返回值:2
示例2
输入:[3,3,3,3,2,2,2]
返回值:3
示例3
输入:[1]
返回值:1
解法一:HashMap
思路:
统计数组中每个元素出现的次数,然后逐个判断出现次数即可。
代码:
import java.util.*;
public class Solution {
public int MoreThanHalfNum_Solution(int [] array) {
if(array.length == 0){
return 0;
}
int len = array.length;
int threshold = len/2;
Map<Integer,Integer> map = new HashMap<>();
for(int i = 0; i < len; i++){
if(!map.keySet().contains(array[i])){
map.put(array[i],1);
}else{
map.put(array[i],map.get(array[i])+1);
}
}
for(Integer key: map.keySet()){
if(map.get(key) > threshold){
return key;
}
}
return 0;
}
}
解法二:排序
思路:
既然某个元素在数组中出现次数超过了一半,那数组中间位置的值一定是满足条件的。
代码:
import java.util.*;
public class Solution {
public int MoreThanHalfNum_Solution(int [] array) {
Arrays.sort(array);
return array[array.length/2];
}
}
解法三:候选法
思路:
使用 cnt 来统计一个元素出现的次数,当遍历到的元素和统计元素相等时,令 cnt++,否则令 cnt--。如果前面查找了 i 个元素,且 cnt == 0,说明前 i 个元素没有 majority,或者有 majority,但是出现的次数少于 i / 2 ,因为如果多于 i / 2 的话 cnt 就一定不会为 0 。此时剩下的 n - i 个元素中,majority 的数目依然多于 (n - i) / 2,因此继续查找就能找出 majority
代码:
public class Solution {
public int MoreThanHalfNum_Solution(int [] array) {
int cnt = 1;
int majority = array[0];
for(int i =1; i < array.length; i++){
cnt = majority == array[i] ? cnt+1 : cnt-1;
if(cnt == 0){
majority = array[i];
cnt = 1;
}
}
int count =0;
for(int val : array){
if(val == majority){
count++;
}
}
if(count > array.length/2){
return majority;
}
return 0;
}
}