摩尔投票法

简介: 摩尔投票法

提问:给定一个int型数组,找出该数组中出现次数大于数组长度一半的int值。

解决方案:遍历该数组,统计每个int值出现次数,再遍历该数组,找出出现次数大于数组长度一半的int值。

同样的,该解决办法也要求使用Map,否则无法达到线性的时间复杂度。

那么对于这个问题,有没有什么不使用Map的线性算法呢?

答案就是今天我们要提到的摩尔投票法。利用该算法来解决这个问题,我们可以达到线性的时间复杂度以及常量级的空间复杂度。

首先我们注意到这样一个现象:在任何数组中,出现次数大于该数组长度一半的值只能有一个。

通过数学知识,我们可以证明它的正确性,但是这并不在我们这篇博客里涉及。

摩尔投票法的基本思想很简单,在每一轮投票过程中,从数组中找出一对不同的元素,将其从数组中删除。这样不断的删除直到无法再进行投票,如果数组为空,则没有任何元素出现的次数超过该数组长度的一半。如果只存在一种元素,那么这个元素则可能为目标元素。

那么有没有可能出现最后有两种或两种以上元素呢?根据定义,这是不可能的,因为如果出现这种情况,则代表我们可以继续一轮投票。因此,最终只能是剩下零个或一个元素。

在算法执行过程中,我们使用常量空间实时记录一个候选元素c以及其出现次数f©,c即为当前阶段出现次数超过半数的元素。根据这样的定义,我们也可以将摩尔投票法看作是一种动态规划算法。

程序开始之前,元素c为空,f©=0。遍历数组A:

如果f©为0,表示截至到当前子数组,并没有候选元素。也就是说之前的遍历过程中并没有找到超过半数的元素。那么,如果超过半数的元素c存在,那么c在剩下的子数组中,出现次数也一定超过半数。因此我们可以将原始问题转化为它的子问题。此时c赋值为当前元素, 同时f©=1。

如果当前元素A[i] == c, 那么f© += 1。(没有找到不同元素,只需要把相同元素累计起来)

如果当前元素A[i] != c,那么f© -= 1 (相当于删除1个c),不对A[i]做任何处理(相当于删除A[i])

如果遍历结束之后,f©不为0,则找到可能元素。

再次遍历一遍数组,记录c真正出现的次数,从而验证c是否真的出现了超过半数。上述算法的时间复杂度为O(n),而由于并不需要真的删除数组元素,我们也并不需要额外的空间来保存原始数组,空间复杂度为O(1)。

看java代码示例,为了保证每一步骤的清晰性,代码没有经过优化。

640.png

其实这样的算法也可以衍生到其它频率的问题上,比如说,找出所有出现次数大于n/3的元素。同样可以以线性时间复杂度以及常量空间复杂度来实现。


目录
相关文章
|
6月前
|
存储 算法
摩尔投票的原理详解
摩尔投票的原理详解
150 1
|
6月前
DAY-3 | 摩尔投票法:巧求众数问题
LeetCode 链接:[Majority Element](https://leetcode.cn/problems/majority-element/)。这道题要求找到数组中出现次数超过数组长度一半的元素,也称为众数。文章介绍了使用摩尔投票法来解决此类问题,这种方法通过相互抵消的方式高效地找到多数元素。首先假设第一个元素是众数,然后遍历数组,遇到相同元素计数加一,不同元素计数减一,计数为零时更换假设的众数。最后计数不为零的元素即为众数。此外,还讨论了摩尔投票法的拓展应用和暴力统计的解法。
96 5
|
算法
Boyer-Moore 投票算法
这里先贴题目:
83 0
|
算法 JavaScript Android开发
LeetCode 周赛上分之旅 #33 摩尔投票派上用场
学习数据结构与算法的关键在于掌握问题背后的算法思维框架,你的思考越抽象,它能覆盖的问题域就越广,理解难度也更复杂。在这个专栏里,小彭与你分享每场 LeetCode 周赛的解题报告,一起体会上分之旅。
78 0
|
存储 算法 JavaScript
你听说过摩尔投票法吗?
你听说过摩尔投票法吗?
270 0
你听说过摩尔投票法吗?
【LeetCode169】多数元素(摩尔投票法)
先用sort排序后,因为定义的“多数元素”是在数组中出现次数大于n/2的元素,所以可以返回下标为n/2的数组元素即所求。 用sort的时间复杂度就是O(nlogn)而非O(n)了。
96 0
【LeetCode169】多数元素(摩尔投票法)
|
人工智能
AlphaGo单挑五虎将获胜,连笑配对AlphaGo笑到最后
经历过 AlphaGo与柯洁第一场势均力敌,第二场热血沸腾的比赛之后,今天,乌镇围棋峰会进入了配对赛与团体赛的争夺。上午 10:59 分,连笑八段联手 AlphaGo 执白战胜古力九段与 AlphaGo 的组合,赢得了史上首次人机配对赛。而在下午 16::32 时,五位世界冠军组成的团队在与 AlphaGo 的对决中收官阶段认输,团体赛告于段落。
333 0
AlphaGo单挑五虎将获胜,连笑配对AlphaGo笑到最后
分橘子问题-日本著名数学游戏专家中村义作教授提出这样一个问题:父亲将2520个桔子分给六个儿子...
题目描述 父亲将2520个桔子分给六个儿子。分完后父亲说:“老大将分给你的桔子的1/8给老二;老二拿到后连同原先的桔子分1/7给老三;老三拿到后连同原先的桔子分1/6给老四;老四拿到后连同原先的桔子分1/5给老五;老五拿到后连同原先的桔子分1/4给老六;老六拿到后连同原先的桔子分1/3给老大”。结果大家手中的桔子正好一样多。问六兄弟原来手中各有多少桔子?