题目描述
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为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 res = array[array.length / 2];
int count = 0;
for (int i : array) {
if (i == res)
count++;
if (count > array.length / 2)
return res;
}
return 0;
}
}
哈希法
使用一个哈希表存储数组中出现过的值的次数
import java.util.ArrayList;
import java.util.HashMap;
public class Solution {
public int MoreThanHalfNum_Solution(int[] array) {
HashMap<Integer, Integer> hashMap = new HashMap<>();
int len = array.length;
for (int i = 0; i < len; i++) {
hashMap.put(array[i], hashMap.getOrDefault(array[i], 0) + 1);
if (hashMap.get(array[i]) > len / 2)
return array[i];
}
return 0;
}
}
最优解法
若数组中存在出现次数超过数组长度一半的数,那么这个数的出现次数会超过所有其他数字的出现次数之和,可以使用两个变量
count
和
res
分别记录元素出现的次数和元素的值,注意,这里的次数并非元素出现的真正次数。初始化
count=1, res=array[0]
,然后遍历数组,若当前元素值和
res
相同,则
count++
,否则
count--
,当
count=0
时将
res
设置为当前元素的值,并将
count=1
。如果有超过数组长度一半的元素存在,那么最后的
res
必定是这个元素,并且它的
count>0
,因为它出现的次数超过数组其他元素出现的次数之和,所以不会减到0,当然
count>0
并不意味着
res
的出现次数超过数组长度的一半,因为数组中可能也不存在出现次数超过数组长度一半的元素,此时仍能满足
count>0
。因此需要再遍历一次数组,判断
res
出现的次数是否大于数组长度的一半
import java.util.ArrayList;
public class Solution {
public int MoreThanHalfNum_Solution(int[] array) {
int count = 1, res = array[0];
for (int v : array) {
if (count == 0) {
count = 1;
res = v;
}
if (v == res)
count++;
else
count--;
}
count = 0;
for (int v : array) {
if (v == res) {
count++;
if (count > array.length / 2)
return res;
}
}
return 0;
}
}