问题描述:
遇到一个算法的题目,找到数组中出现次数最多的数,并且判断是否超过了数组一半。
解决方案
我最开始想了3种方案,
第一种:用hashSet把数据传入,并且记录false的次数,最后和数组长度比较。
第二种:用两个指针循环比较数据有没有重复的,有的话count+1,最和数组长度比较。
第三种:第三种就是本文要介绍的一种算法,摩尔投票法。前面两种都能实现功能,但有个问题,在复杂度和空间都很高。
摩尔投票法
public static void main(String[] args) {
/**
* 如果数组中多一半的数都是同一个,则称之为主要元素。给定一个整数数组,找到它的主要元素。若没有,返回-1。
*
* 示例 1:
* 输入:[1,2,5,9,5,9,5,5,5]
* 输出:5
*
* 示例 2:
* 输入:[3,2]
* 输出:-1
*
* 示例 3:
* 输入:[2,2,1,1,1,2,2]
* 输出:2
*
*/
int[] nums = {
1,2,5,9,5,9,5,5,5};
int i = 0;
int count1 = 0;
//遍历整个数组,在遍历的过程中找到出现次数最多的数
for (int num : nums) {
if (count1 == 0) {
i = num;
count1++;
} else {
if (i == num) {
count1++;
} else {
count1--;
}
}
}
int count2 = 0;
//先判断是否有众数
if (count1 <= 0) {
System.out.println(i);
} else {
//确认有众数之后就遍历数组 确定众数出现的次数
for (int num : nums) {
if (num == i) {
count2 ++;
}
}
}
//判断出现的次数是否超过数组的一半
if (count2 > nums.length / 2) {
System.out.println(i);
}
}
总结
这个算法不止可以找到出现次数超过数组长度一半,也可以找到三分之一的等等,都可以找到。