【算法】投票算法

【适用场景】

给定一个无序数组,有n个元素,找出其中的一个多数元素,多数元素出现的次数大于⌊ n/2 ⌋,注意数组中也可能不存在多数元素。
注意:多数元素n>2,即投票的某个元素超过半数。

【算法思路理解】

采用的是 “支持票” 和 “反对票” 抵扣的思路。

1.A表示支持票,B表示反对票
采用A、B互相抵扣,最终剩余的类型就是投票结果(大于半数)
image

2.但实际用到的投票算法中,一般不止“支持票”、“反对票”两种形态。如下:

  • 大于半数的元素A,和其他元素两两抵扣后,剩余的元素一定是A
    image
  • 但,实际的投票算法中,初始我们是不A是“大于半数元素”,无法按照上图进行A 和 other抵扣。
    反而采用的是如下 按照 顺序逐个抵扣的方式:
    image
    其中C和D抵扣的这种方式,知会导致算法抵扣后最终剩余的“大于半数元素”A更多,不会导致“大于半数元素”统计错误。

【注】:

  • 一定是“大于半数元素场景”;
  • 对于统计序列中数量最多元素、但是最大元素“不多于半数”场景不适用,如下:
    image

【算法实现】

需要记录两个信息:

  • 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;
    }
}

【扩展】

当然,也可不采用投票算法的方式:

  1. 序列排序。
  2. 中间元素一定是求的“大于半数元素”
posted @ 2021-05-29 16:19  小拙  阅读(438)  评论(0编辑  收藏  举报