169、多数元素这道题的官方题解有一种算法个人感觉比较有趣,就是标题写的Boyer-Moore 投票算法。但是感觉官方没把这个算法讲清楚。所以我整合了一下各位评论区和题解区大佬的发言,讲讲这个算法。
对这题利用投票算法解题的分析可以看看官方题解和这位大佬的博客。其实都讲的挺好但是还是比较抽象。
我在看官方题解的时候看到一位大佬的评论:
如果候选人不是maj 则 maj,会和其他非候选人一起反对 会反对候选人,所以候选人一定会下台(maj==0时发生换届选举)
如果候选人是maj , 则maj 会支持自己,其他候选人会反对,同样因为maj 票数超过一半,所以maj 一定会成功当选
什么意思呢?我第一次看这个方法的题解,就在想如果第一次选到的candidate不是多数元素怎么办,看到这条评论我懂了。
如果我们选到的candidate不是多数元素,那么一定会在某一处被非candidate反对下台,为什么?因为非candidate里有握有半数以上选票的多数元素。
我们用一个最极端的例子来具象化这一想法:
[1,1,1,1,0,0,0,0,0]
按照投票算法的思路,我们一开始选择的candidate为1,就算它前期积累非常多的选票,等着它的也是至少多一票的反对票,因为它不是多数元素。
那后来我又想,为什么会在count重新变为0的时候替换candidate,意思就是为什么能够分出这样一些组合。那我们其实不要禁锢在究竟是什么数这样的思想上,把这些数分成两堆,一堆是多数元素,一堆不是多数元素,就拿官方题解中的例子来说明:
[7, 7, 5, 7, 5, 1, 5, 7, 5, 5, 7, 7 ,7, 7, 7, 7]
很显然多数元素为7
------------------------------------------------------>
[5, 1, 5, 5, 5, 5 , 7, 7, 7, 7, 7, 7, | 7, 7, 7, 7]
分成这样两波,就对应了上面的说法:如果一开始没有选到candidate多数元素,就算它前期积累非常多的选票,等着它的也是至少多一票的反对票。
那么当当前的candidate(候选人)被反对下台之后,就可以选取新的candidate,继续进行投票。知道找出支持票多的候选人(即多数元素)。那么把下属例子打乱,就会产生多处候选人被反对下台的情况,就算这一分块里是多数元素被反对下台了,也不可能影响宏观上多数元素票数更多的事实。在所有的反对票(非多数元素)都被相同数量的支持票(多数元素)消耗后,最后candidate一定会选到多数元素。每一分块开始都重置candidate并不是为了选出每一分块的多数元素,而是为了选到最后胜出的多数元素。
[5, 1, 5, 5, 5, 5, 7, 7, 7, 7, 7, 7, | 7, 7, 7, 7]
上述思路值适用于像多数元素这样明确表示多数元素一定存在的情况。若多数元素可能不存在,比如:
[5, 1, 5, 5, 5, 5, 7, 7, 7, 7, 7, 7]
那么最后得到的结果就会是5。解决方法就是拿着当前得出的值进行二次遍历,统计该数在数组中出现的次数,看是否大于 ⌊ n/2 ⌋ 。
还有一个就是,多数元素这道题里的多数元素指的是在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素而不是出现次数最多的数,就像上面的例子,7虽然不是出现次数大于 ⌊ n/2 ⌋ 的元素,但(在这儿停顿)是出现次数最多的数,能不能用投票算法呢?