当前位置: 首页 > ops >正文

LeetCode百题刷002摩尔投票法

遇到的问题都有解决的方案,希望我的博客可以为你提供一些帮助

图片源自leetcode 

题目:169. 多数元素 - 力扣(LeetCode)

一、排序法

题目要求需要找到多数值(元素个数>n/2)并返回这个值。一般会想到先排个序,再取中间值;因为在有序数组中多数值(元素个数>n/2)的中间值必定是多数值。

代码如下:

class Solution:def majorityElement(self, nums: List[int]) -> int:nums.sort()return nums[len(nums)//2]
class Solution {
public:int majorityElement(vector<int>& nums) {sort(nums.begin(),nums.end());return nums[nums.size()/2];}
};

复杂度分析 

时间复杂度:O(nlogn)

使用的排序算法时间复杂度是O(nlogn)

空间复杂度:O(1)

 在原数组上排序,无额外空间开销

结果

二、哈希表法

一个比较常规的思路是:对于每一个元素我可以记录它出现的次数,最后返回出现次数最多的元素就行。这样问题就变成了如何在无序的数组中精确的识别出每一个元素,并且记录他们出现的次数。哈希表天然适配,哈希表提供key-value键值映射,key可用于记录数组中的元素,value可用于累计出现的次数。

class Solution:def majorityElement(self, nums: List[int]) -> int:ans={}for num in nums:ans [num]=ans.get(num,0)+1return max(ans,key=ans.get)
class Solution {
public:int majorityElement(vector<int>& nums) {unordered_map<int ,int> ans;int n=nums.size();for (auto num :nums){ans[num]++;if (ans[num]>n/2){return num;}}return -1;}
};

复杂度分析:

 时间复杂度:O(n)只需要遍历一次数组

空间复杂度:O(n)最坏情况下需要与元素组等大的空间,但在本题目中明确指出了多数元素是存在的所以最多需要空间不大于 n/2

 三、摩尔投票法(Boyer-Moore Voting Algorithm)

1. 基本思想

摩尔投票法是一种用于 快速寻找数组中出现次数超过一定比例的元素 的算法。其核心思想是通过 “抵消” 策略,在遍历数组时维护候选元素及其计数,最终找到可能的众数。

  • 经典问题:在数组中找出出现次数超过 n/2 的元素(即严格众数)。

  • 扩展问题:找出所有出现次数超过 n/k 的元素(如 k=3,找出出现次数超过 n/3 的元素)。

2. 算法步骤(以寻找严格众数为例)
  1. 初始化
    设置候选元素 candidate 和计数器 count,初始值为 None 和 0

  2. 遍历数组
    对每个元素 num

    • 如果 count == 0,设当前元素为候选(candidate = num)。

    • 如果 num == candidate,计数器加一(count += 1)。

    • 否则,计数器减一(count -= 1)。

  3. 验证结果
    最终需再次遍历数组,确认 candidate 的出现次数是否超过 n/2

3. 示例分析

以数组 nums = [3, 2, 3] 为例,寻找严格众数(出现次数 > 3/2 = 1.5,即至少出现 2 次):

步骤当前元素candidatecount操作
1331count=0 → 选为候选
2230不同 → count减1
3331count=0 → 重新选为候选

最后验证 3 出现 2 次,满足条件。

4. 扩展:寻找出现次数超过 n/k 的元素

若需找出所有出现次数超过 n/k 的元素(例如 k=3),需维护 k-1 个候选元素及其计数器。

步骤

  1. 初始化
    维护 k-1 个候选和计数器,如 candidate1, count1 和 candidate2, count2(当 k=3 时)。

  2. 遍历数组

    • 若当前元素与任一候选相同,对应计数器加一。

    • 若不同且某计数器为 0,替换候选并重置计数器为 1。

    • 否则,所有计数器减一。

  3. 验证候选
    统计所有候选的实际出现次数,确认是否超过 n/k

5. 对于本题目而言如何应用

思路
多数元素出现次数大于数组长度一半,利用抵消思想,每次找到两个不同元素就抵消掉,最后剩下的就是多数元素。遍历数组,维护一个候选元素 candidate 和其出现次数 count 。遇到相同元素,count 加 1;遇到不同元素,count 减 1 ,若 count 为 0 ,更新 candidate 为当前元素并将 count 设为 1 。

class Solution:def majorityElement(self, nums: List[int]) -> int:candidate = Nonecount = 0for num in nums:if count == 0:candidate = numcount += 1 if num == candidate else -1# 验证return candidate if nums.count(candidate) > len(nums) // 2 else -1
class Solution {
public:int majorityElement(vector<int>& nums) {int condidate =NULL;int count=0;for (auto num:nums){if (count==0){condidate=num;}count=count++?condidate==num:count--;}return condidate;}
};
寻找出现次数超过 n/3 的元素
def majorityElement_3(nums):candidate1, count1 = None, 0candidate2, count2 = None, 0for num in nums:if num == candidate1:count1 += 1elif num == candidate2:count2 += 1elif count1 == 0:candidate1, count1 = num, 1elif count2 == 0:candidate2, count2 = num, 1else:count1 -= 1count2 -= 1# 验证候选res = []for c in [candidate1, candidate2]:if nums.count(c) > len(nums) // 3:res.append(c)return res

结果:

6. 复杂度分析
  • 时间复杂度:O(n)
    仅需两次遍历数组(第一次找候选,第二次验证)。本题中只需遍历一次,不需要验证(题干条件已给出一定有多数元素)。

  • 空间复杂度:O(1)
    仅需常数空间存储候选和计数器。


7. 与其他方法对比
方法优点缺点
摩尔投票法O(1) 空间需验证结果
哈希统计直观,可统计所有元素O(n) 空间,不适用于大数据流

摩尔投票法可以在线性时间和常数空间内高效解决多数元素问题,尤其适合处理大规模数据或内存受限的场景。

http://www.xdnf.cn/news/4941.html

相关文章:

  • 镜头内常见的马达类型(私人笔记)
  • Nginx静态资源增加权限验证
  • CurrentHashMap的整体系统介绍及Java内存模型(JVM)介绍
  • 单位代码签名证书是什么?如何申请?
  • 开平机:从原理到实践的全面技术剖析
  • 【C/C++】范围for循环
  • ⭐️⭐️⭐️【课时1:大模型是什么?】学习总结 ⭐️⭐️⭐️ for《大模型Clouder认证:基于百炼平台构建智能体应用》认证
  • 【el-admin】el-admin关联数据字典
  • 访问网站提示“不安全”“有风险”怎么办?
  • HarmonyOS NEXT 免费无广告看电影app:从想法到实现的经验总结
  • AI与自然语言处理(NLP):从BERT到GPT的演进
  • Python字典:数据操作的核心容器
  • 单调栈所有模版(2)
  • 19、HashTable(哈希)、位图的实现和布隆过滤器的介绍
  • 报考消防设施操作员需要满足什么条件?
  • 【Python 字典(Dictionary)】
  • 【Pandas】pandas DataFrame all
  • levelDB的数据查看(非常详细)
  • 摩斯密码详解
  • 基于论文《大规模电动汽车充换电设施可调能力聚合评估与预测》开发者说明文档
  • EXCEL中嵌入其他表格等文件
  • 电子电路:白炽灯发光能说明电子正在消散消失吗?
  • 小刚说C语言刷题—1004阶乘问题
  • 深入了解阻塞队列的实现
  • MySQL性能分析工具:SHOW PROCESSLIST
  • Mac电脑远程连接window系统服务器
  • 自定义分区器
  • 车载以太网转USB接口工具选型指南(2025版)
  • C++ stl中的list的相关函数用法
  • 学习黑客搜索技巧