【算法】投票算法
【适用场景】
给定一个无序数组,有n个元素,找出其中的一个多数元素,多数元素出现的次数大于⌊ n/2 ⌋,注意数组中也可能不存在多数元素。
注意:多数元素n>2,即投票的某个元素超过半数。
【算法思路理解】
采用的是 “支持票” 和 “反对票” 抵扣的思路。
1.A表示支持票,B表示反对票
采用A、B互相抵扣,最终剩余的类型就是投票结果(大于半数)
2.但实际用到的投票算法中,一般不止“支持票”、“反对票”两种形态。如下:
- 大于半数的元素A,和其他元素两两抵扣后,剩余的元素一定是A
- 但,实际的投票算法中,初始我们是不A是“大于半数元素”,无法按照上图进行A 和 other抵扣。
反而采用的是如下 按照 顺序逐个抵扣的方式:
其中C和D抵扣的这种方式,知会导致算法抵扣后最终剩余的“大于半数元素”A更多,不会导致“大于半数元素”统计错误。
【注】:
- 一定是“大于半数元素场景”;
- 对于统计序列中数量最多元素、但是最大元素“不多于半数”场景不适用,如下:
【算法实现】
需要记录两个信息:
- candidate:记录抵扣后,剩余的元素
- count:记录抵扣后,剩余的元素数量,初始为0
【样例】:求众数
给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例:
输入:[2,2,1,1,1,2,2]
输出:2
代码参考:
public class MaxNumElement {
public Integer getMaxNumElement(Integer[] array) {
Integer element = -1;
Integer count = 0;
for (int i =0; i<array.length; i++) {
if (count > 0) {
if (element != array[i]) {
count--;
} else {
count++;
}
} else {
element = array[i];
count++;
}
}
return element;
}
}
【扩展】
当然,也可不采用投票算法的方式:
- 序列排序。
- 中间元素一定是求的“大于半数元素”