前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >图解算法 | 摩尔投票法求多数元素

图解算法 | 摩尔投票法求多数元素

作者头像
江不知
发布2020-03-18 17:51:59
6K0
发布2020-03-18 17:51:59
举报
文章被收录于专栏:编程拯救世界编程拯救世界
算法描述

摩尔投票法(Boyer–Moore majority vote algorithm),也被称作「多数投票法」,算法解决的问题是:如何在任意多的候选人中(选票无序),选出获得票数最多的那个

算法可以分为两个阶段:

  1. 对抗阶段:分属两个候选人的票数进行两两对抗抵消
  2. 计数阶段:计算对抗结果中最后留下的候选人票数是否有效

这样说比较抽象,我们直接来看一道题:LeetCode 169. 多数元素[1]

例题:多数元素

给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。

你可以假设数组是非空的,并且给定的数组总是存在多数元素。

示例 1:

代码语言:javascript
复制
输入: [3,2,3]
输出: 3

示例 2:

代码语言:javascript
复制
输入: [2,2,1,1,1,2,2]
输出: 2

投票法思路

根据上述的算法思想,我们遍历投票数组,将当前票数最多的候选人与其获得的(抵消后)票数分别存储在 majorcount 中。

当我们遍历下一个选票时,判断当前 count 是否为零:

  • count == 0,代表当前 major 空缺,直接将当前候选人赋值给 major,并令 count++
  • count != 0,代表当前 major 的票数未被完全抵消,因此令 count--,即使用当前候选人的票数抵消 major 的票数

详细图解

[2,2,1,3,1,2,2] 为例。

遍历数组第一个元素 2 时,因 major 空缺,所以赋值 major = 2,且票数 count = 1

我们发现第二个元素依旧是「候选人」2,与 major 相同,因此将票数加一:

第三个元素是 1,与 major 不同,因此发生「对抗」,将当前 major 的票数冲抵掉 1 票:

第四个元素是 3,又与 major 不同,因此产生「对抗」,票数继续冲抵:

当遍历到第五个元素 1 时,我们发现当前 count 已经归 0,说明 major 位置空缺,因此我们令 major = 1,且 count = 1

第六个元素是 2,与 major 不同,因此进行票数抵消,元素 1 刚上位又要下台了:

此时 count 又归零了,因此当遍历到最后一个元素 2 时,令 major = 2,票数 count = 1

至此遍历结束,求出的多数元素为元素 2

具体实现

Python
代码语言:javascript
复制
class Solution(object):
    def majorityElement(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        major = 0
        count = 0
        
        for n in nums:
            if count == 0:
                major = n
            if n == major:
                count = count + 1
            else:
                count = count - 1

        return major
Go
代码语言:javascript
复制
func majorityElement(nums []int) int {
    major := 0
    count := 0

    for _, num := range nums {
        if count == 0 {
            major = num
        }
        if major == num {
            count += 1
        } else {
            count -= 1
        }
    }
    
    return major
}

复杂度

  • 时间复杂度:,仅遍历一次数组
  • 空间复杂度:,没有使用额外空间

总结

题目中给出条件「给定的数组总是存在多数元素」,因此没有涉及「计数阶段」,仅在「对抗阶段」对候选人票数进行了「对抗抵消」。如果想加深理解,推荐大家可以再做做这道题:LeetCode 229. 求众数 II[2]

参考资料

[1]LeetCode 169. 多数元素: https://leetcode-cn.com/problems/majority-element/

[2]LeetCode 229. 求众数 II: https://leetcode-cn.com/problems/majority-element-ii/

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-03-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 编程拯救世界 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 例题:多数元素
    • 投票法思路
      • 详细图解
        • 具体实现
          • Python
          • Go
        • 复杂度
        • 总结
          • 参考资料
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档