Java中找数组众数最经典高效的方法是摩尔投票法:先遍历用抵消思想选出候选者,再二次遍历验证其出现次数是否超过一半,时间复杂度O(n),空间复杂度O(1)。

Java 中找出数组中出现次数超过一半的元素,最经典高效的方法是 摩尔投票法(Boyer-Moore Majority Vote Algorithm),时间复杂度 O(n),空间复杂度 O(1),无需额外哈希表。
摩尔投票法:一次遍历找出候选者
核心思想是“抵消”:把众数看作主力军,其他数是杂兵。主力军人数 > 其他所有人数之和,所以两两配对抵消后,最后剩下的一定是众数。
- 初始化
candidate = null,count = 0 - 遍历数组:
- 若
count == 0,将当前元素设为candidate,count = 1 - 否则,若当前元素等于
candidate,count++;否则count--
- 若
- 遍历结束后,
candidate是唯一可能的众数(但需验证)
必须验证:确认 candidate 确实出现超半数
摩尔投票只保证:如果众数存在,它一定会被选出;但它不保证 candidate 一定满足条件(比如数组无众数时也会返回一个值)。所以第二步必不可少:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 重新遍历数组,统计
candidate的实际出现次数 - 若次数 >
nums.length / 2(注意用整数除法,Java 中length/2向下取整,所以判断用count > nums.length / 2即可),则返回该元素 - 否则返回特殊值(如抛异常、返回 -1 或 Optional.empty())
完整可运行代码示例
// 假设输入为 int[] nums,非空
立即学习“Java免费学习笔记(深入)”;
public static int majorityElement(int[] nums) {
// 第一阶段:投票找候选者
int candidate = nums[0], count = 1;
for (int i = 1; i < nums.length; i++) {
if (count == 0) {
candidate = nums[i];
count = 1;
} else if (nums[i] == candidate) {
count++;
} else {
count--;
}
}
// 第二阶段:验证
count = 0;
for (int num : nums) {
if (num == candidate) count++;
}
if (count > nums.length / 2) {
return candidate;
} else {
throw new IllegalArgumentException("No majority element");
}
}
其他方法对比(了解即可)
-
哈希表计数:遍历一次,用
HashMap统计频次,再遍历 map 找 value > n/2 的 key。时间 O(n),空间 O(n) - 排序取中位数:排序后,众数必在中间位置(因占 >50%)。时间 O(n log n),空间 O(1)(原地排序)。适用于允许修改原数组或不介意开销的场景
- 随机采样:随机选元素检查是否为众数,期望时间 O(n),但有概率失败,一般不用于正式解法

















