题目解析
问题描述
小R从班级中抽取了一些同学,每位同学都会给出一个数字。已知在这些数字中,某个数字的出现次数超过了数字总数的一半。现在需要你帮助小R找到这个数字。
测试样例
样例1:array = [1, 3, 8, 2, 3, 1, 3, 3, 3],输出:3
样例2:array = [5, 5, 5, 1, 2, 5, 5],输出:5
样例3:array = [9, 9, 9, 9, 8, 9, 8, 8],输出:9
解题思路
摩尔投票算法:摩尔投票算法是一种用于解决“多数元素”问题的经典算法。其核心思想是通过抵消不同的元素来找到出现次数超过一半的元素。
1、初始化
候选元素 candidate 初始化为 0。
计数器 count 初始化为 0。
2、遍历数组
如果 count 为 0,将当前元素设为 candidate。
如果当前元素等于 candidate,则 count 加 1。
否则,count 减 1。
3、返回结果:
最终 candidate 就是我们要找的元素。
图解示例
假设输入数组为 [1, 3, 8, 2, 3, 1, 3, 3, 3] :
最终 candidate 为 3,即数组中出现次数超过一半的元素。
代码详解
public static int solution(int[] array) {
// 初始化候选元素和计数器
int candidate = 0;
int count = 0;
// 遍历数组
for (int num : array) {
// 如果计数器为0,设置当前元素为候选元素
if (count == 0) {
candidate = num;
}
// 如果当前元素等于候选元素,计数器加1
if (num == candidate) {
count++;
} else {
// 否则,计数器减1
count--;
}
}
// 返回候选元素
return candidate;
}
public static void main(String[] args) {
// 测试用例
System.out.println(solution(new int[]{1, 3, 8, 2, 3, 1, 3, 3, 3}) == 3);
}
}
代码解释
1、初始化
int candidate = 0; int count = 0;
candidate 用于存储当前的候选元素; count 用于记录候选元素的出现次数。
2、遍历数组
if (count == 0) {
candidate = num;
}
if (num == candidate) {
count++;
} else {
count--;
}
}
3、返回结果
return candidate;
最终 candidate 就是我们要找的元素。
测试用例
// 测试用例
System.out.println(solution(new int[]{1, 3, 8, 2, 3, 1, 3, 3, 3}) == 3);
}
该测试用例验证了代码的正确性,输出结果为 true,表示代码正确找到了出现次数超过一半的元素。
总结
为什么摩尔投票算法有效?
摩尔投票算法的核心在于“抵消”。假设数组中存在一个出现次数超过一半的元素 x,那么在遍历数组的过程中,所有非 x 的元素都会被 x 抵消掉。具体来说: 如果当前元素是 x,计数器 count 加 1。 如果当前元素不是 x,计数器 count 减 1。 由于 x 的出现次数超过一半,因此在遍历结束后,count 一定大于 0,且 candidate 就是 x。 算法的正确性 初始化:candidate 和 count 初始化为 0,表示当前没有候选元素。 遍历过程: 如果 count 为 0,表示当前没有候选元素,将当前元素设为候选元素。 如果当前元素等于候选元素,计数器加 1。 如果当前元素不等于候选元素,计数器减 1。 返回结果:遍历结束后,candidate 就是我们要找的元素。
摩尔算法总结
摩尔投票算法的核心在于通过“抵消”不同元素的方式,最终留下出现次数超过一半的元素。假设存在这样一个多数元素,那么在遍历数组的过程中,任何非多数元素与其抵消一次后,多数元素仍然会保持优势(即出现次数仍然最多)。摩尔投票算法不仅适用于找出数组中出现次数超过一半的元素,还可以扩展到其他问题中,如找出出现次数最多的元素(如果存在的话,且出现次数大于等于n/k,其中k是一个常数)。提供的示例代码很好地实现了摩尔投票算法。通过遍历数组,并根据当前元素与候选元素的关系更新计数器和候选元素,最终得到了出现次数超过一半的元素。摩尔投票算法是一种高效且简洁的解决“多数元素”问题的算法。其核心思想在于通过抵消不同元素来找出多数元素,具有线性时间复杂度和常数空间复杂度的优势。在实际应用中,摩尔投票算法具有广泛的应用前景和重要的实用价值。