一、题目描述
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
二、思路分子及代码实现
方法一:数学法(排序)
思路分析:
由于使用的数组,我们很容易想到利用下标的特征来计数,所以采用数组排序、下标计数的方法。
代码实现:
import java.util.Arrays;
public class Solution {
public int MoreThanHalfNum_Solution(int [] array) {
//最简单的方法,先对数组进行排序
Arrays.sort(array);
int len=array.length;
if(len==1)return array[0];
for(int i=0;i<len/2;i++){
if(array[i]==array[i+len/2])
return array[i];
}
return 0;
}
}
方法二:统计法
使用HashMap来存储数组中的数据和相应的次数
然后遍历HashMap找出出现次数超过一半的元素
import java.util.HashMap;
public class Solution {
public int MoreThanHalfNum_Solution(int [] array) {
HashMap<Integer,Integer> map=new HashMap<Integer,Integer>();
for(int i=0;i<array.length;i++){
if(map.containsKey(array[i])){
map.put(array[i],map.get(array[i])+1);
}else{
map.put(array[i],1);
}
}
for(int s:map.keySet()){
if(map.get(s)>array.length/2){
return s;
}
}
return 0;
}
}
方法三:阵地守营思想
思路分析:
数组中有一个数字出现的次数超过数组长度的一半,也就是说它出现的次数比其他所有数字出现次数的和还要多。
因此我们可以考虑在遍历数组的时候保存两个值:一个是数组的一个数字,一个是次数。
当我们遍历到下一个数字的时候,如果下一个数字和我们之前保存的数字相同,则次数加1;如果下一个数字和我们之前保存的数字不同,则次数减1。如果次数为零,我们需要保存下一个数字,并把次数设为1。
由于我们要找的数字出现的次数比其他所有数字出现的次数之和还要多,那么要找的数字肯定是最后一次把次数设为1时对应的数字。
代码实现:
import java.util.Arrays;
public class Solution {
public int MoreThanHalfNum_Solution(int [] array) {
if(array==null) return 0;
if(array.length==1) return array[0];
int count=1;
int value=array[0];
for(int i=1;i<array.length;i++){
if(value==array[i]){
count++;
}else{
count--;
if(count==0){
value=array[i];
count=1;
}
}
}
int times=0;
if(count>0){
for(int i=0;i<array.length;i++){
if(value==array[i]) times++;
}
if(times>array.length/2)
return value;
return 0;
}
return 0;
}
}