剑指offer-数组中出现超过一半的数字
题目描述
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
解题思路
1、方式一:利用map映射。找出超过数组长度一半的数字,关键在于将值和次数进行一个映射。这时我们就可以想到Map<Key,Value>进行映射,Key对应的是值,而Value对应的是对应值出现的次数。
2、利用哨兵,声明一个和数组一样大小的标志位数组,所有位置的值都设置为1,我们遍历下标0到下标数组长度/2的值,当后面的数和当前一个数值相同,我们就加1,不同就减1,如果最后再次遍历标志位数组,发现有大于0位置的值,我们返回这个值。
值得注意的是我们要对特殊情况进行单独讨论,如果数组大小为1.直接返回这个值,但是上面的方法如果数组大小为奇数值(除去大小为1的情况),就有可能返回错误答案,如{1,2,3,4,5,6,7}就会返回3,因为4的标志位1,但是他并不满足要求。所以我们必须看数组长度/2位置的数是否所以的数和它相同,只有这样才能返回这个数,所以必须单独讨论。
代码块1-利用map映射
import java.util.HashMap;
public class Solution {
public static int MoreThanHalfNum_Solution(int [] array) {
HashMap<Integer,Integer> map=new HashMap<Integer,Integer>();
for (int i = 0; i < array.length; i++) {
if(map.get(array[i])!=null){
map.put(array[i], map.get(array[i])+1);
if(map.get(array[i])>array.length/2){
return array[i];
}
}else{
if(array.length==1) return array[0];
map.put(array[i], 1);
}
}
return 0;
}
}
代码块二-设立哨兵
import java.util.HashMap;
public class Solution {
public static int MoreThanHalfNum_Solution(int [] array) {
int[] count=new int[array.length];
if(array.length==1) return array[0];
boolean flag=true;
for(int i=array.length/2+1;i<array.length;i++){
if(array[i]!=array[array.length/2]){
flag=false;
}
}
if(flag){
return array[array.length/2];
}
for (int i = 0; i < array.length/2; i++) {
count[i]=1;
for(int j=i+1;j<array.length;j++){
if(array[i]==array[j]){
count[i]++;
}
else{
count[i]--;
}
}
}
for (int i = 0; i < count.length/2; i++) {
if(count[i]>0){
return array[i];
}
}
return 0;
}
}