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.mzph.cn/web/79469.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android Studio Gradle 中 只显示 Tasks 中没有 build 选项解决办法

一、问题描述 想把项目中某一个模块的代码单独打包成 aar ,之前是点击 AndroidStudio 右侧的 Gradle 选项&#xff0c;然后再点击需要打包的模块找到 build 进行打包&#xff0c;但是却发现没有 build 选项。 二、解决办法 1、设置中勾选 Configure all Gradle tasks… 选项 …

深入浅出之STL源码分析2_stl与标准库,编译器的关系

引言 在第一篇博客中&#xff0c;深入浅出之STL源码分析1_vector基本操作-CSDN博客 我们将引出下面的几个问题 1.刚才我提到了我的编译器版本是g 11.4.0&#xff0c;而我们要讲解的是STL&#xff08;标准模板库&#xff09;&#xff0c;那么二者之间的关系是什么&#xff1f;…

(十二)深入了解AVFoundation-采集:人脸识别与元数据处理

&#xff08;一&#xff09;深入了解AVFoundation&#xff1a;框架概述与核心模块解析-CSDN博客 &#xff08;二&#xff09; 深入了解AVFoundation - 播放&#xff1a;AVFoundation 播放基础入门-CSDN博客 &#xff08;三&#xff09;深入了解AVFoundation-播放&#xff1…

Kafka 与 RabbitMQ、RocketMQ 有何不同?

一、不同的诞生背景&#xff0c;塑造了不同的“性格” 名称 背景与目标 产品定位 Kafka 为了解决 LinkedIn 的日志收集瓶颈&#xff0c;强调吞吐与持久化 更像一个“可持久化的分布式日志系统” RabbitMQ 出自金融通信协议 AMQP 的实现&#xff0c;强调协议标准与广泛适…

配置 Web 服务器练习

一、要求 1.通过https://ip 可以访问到网站首页 2.通过 https://ip/private/ 实现用户访问控制&#xff0c;仅允许已经添加的 tom&#xff0c;jerry 能够访问到 private 子路径的界面 3.通过 https://ip/vrit/ 实现能够访问到将系统 /nginx/virt 目录下的网页文件&#xff0…

MySQL索引详解(下)(SQL性能分析,索引使用)

索引是MySQL性能优化的核心&#xff0c;但如何精准分析查询瓶颈、合理设计索引&#xff0c;是开发者必须掌握的技能。本文结合实战案例&#xff0c;系统讲解SQL性能分析工具链与索引使用技巧&#xff0c;帮助读者构建高性能数据库系统。 一、SQL性能分析&#xff1a;从宏观到微…

招行数字金融挑战赛数据赛道赛题一

赛题描述&#xff1a;根据提供的用户行为数据&#xff0c;选手需要分析用户行为特征与广告内容的匹配关系&#xff0c;准确预测用户对测试集广告的点击情况&#xff0c;通过AUC计算得分。 得分0.6120&#xff0c;排名60。 尝试了很多模型都没有能够提升效果&#xff0c;好奇大…

ORB-SLAM3和VINS-MONO的对比

直接给总结&#xff0c;整体上orbslam3&#xff08;仅考虑带imu&#xff09;在初始化阶段是松耦合&#xff0c;localmap和全局地图优化是紧耦合。而vins mono则是全程紧耦合。然后两者最大的区别就在于vins mono其实没有对地图点进行优化&#xff0c;为了轻量化&#xff0c;它一…

安装typescript时,npm install -g typescript报错

删除C:\Users\用户\下的.npmrc文件,如果你的没有&#xff0c;看是不是因为将隐藏的项目勾选上了&#xff0c;然后去掉勾选。 重新输入

[GESP202503 四级] 二阶矩阵c++

题目描述 小 A 有一个 n 行 m 列的矩阵 A。 小 A 认为一个 22 的矩阵 D 是好的&#xff0c;当且仅当 。其中 表示矩阵 D 的第 i 行第 j 列的元素。 小 A 想知道 A 中有多少个好的子矩阵。 输入 第一行&#xff0c;两个正整数 n,m。 接下来 n 行&#xff0c;每行 m 个整数…

基于flask+pandas+csv的报表实现

基于大模型根据提示词去写SQL执行SQL返回结果输出报表技术上可行的&#xff0c;但为啥还要基于pandas去实现呢&#xff1f; 原因有以下几点&#xff1a; 1、大模型无法满足实时性输出报表的需求&#xff1b; 2、使用大模型比较适合数据量比较大的场景&#xff0c;大模型主要…

Java学习笔记(对象)

一、对象本质 状态&#xff08;State&#xff09;&#xff1a;通过成员变量&#xff08;Field&#xff09;描述 行为&#xff08;Behavior&#xff09;&#xff1a;通过成员方法&#xff08;Method&#xff09;实现 class Person {String name;int age;void eat() {System.o…

Qt学习Day0:Qt简介

0. 关于Qt Qt是C的实践课&#xff0c;之前在C中学习的语法可以有具体的应用场景。Qt的代码量很大&#xff0c;不要死记硬背&#xff0c;学会查询文档的能力更加重要。 建议提升一下相关单词的储备量&#xff1a; 1. Qt是什么&#xff1f; Qt是一个基于C语言的图形用户界面&a…

React知识框架

一、核心概念 1. 组件化开发 核心思想&#xff1a;将 UI 拆分为独立、可复用的组件&#xff08;函数组件/类组件&#xff09;。组件特性&#xff1a;props&#xff08;接收参数&#xff09;、state&#xff08;组件状态&#xff09;、生命周期&#xff08;类组件特有&#xf…

Django之账号登录及权限管理

账号登录及权限管理 目录 1.登录功能 2.退出登录 3.权限管理 4.代码展示合集 这篇文章, 会讲到如何实现账号登录。账号就是我们上一篇文章写的账号管理功能, 就使用那里面已经创建好的账号。这一次登录, 我们分为三种角色, 分别是员工, 领导, 管理员。不同的角色, 登录进去…

[学习]RTKLib详解:convkml.c、convrnx.c与geoid.c

本文是 RTKLlib详解 系列文章的一篇&#xff0c;目前该系列文章还在持续总结写作中&#xff0c;以发表的如下&#xff0c;有兴趣的可以翻阅。 [学习] RTKlib详解&#xff1a;功能、工具与源码结构解析 [学习]RTKLib详解&#xff1a;pntpos.c与postpos.c [学习]RTKLib详解&…

java 破解aspose.words 18.6 使用

资源包&#xff1a;https://download.csdn.net/download/qq_36598111/90787167 jar包是破解过的&#xff0c;直接可以使用。 引入jar&#xff0c;要引入本地的&#xff0c;不要直接引入仓库的 <dependency><groupId>com.aspose</groupId><artifactId>…

vue使用rules实现表单校验——校验用户名和密码

编写校验规则 常规校验 const rules {username: [{ required: true, message: 请输入用户名, trigger: blur },{ min: 5, max: 16, message: 长度在 5 到 16 个字符, trigger: blur }],password: [{ required: true, message: 请输入密码, trigger: blur },{ min: 5, max: 1…

宝塔服务安装使用的保姆级教程

宝塔介绍&#xff1a; 宝塔面板&#xff08;BT Panel&#xff09; 是一款 国产的服务器运维管理面板&#xff0c;主要用于简化 Linux/Windows 服务器的网站、数据库、FTP、防火墙等管理操作。它通过图形化界面&#xff08;Web端&#xff09;和命令行工具&#xff08;bt 命令&a…

数字化转型-4A架构之数据架构

4A架构系列文章 数字化转型-4A架构&#xff08;业务架构、应用架构、数据架构、技术架构&#xff09; 数字化转型-4A架构之业务架构 数字化转型-4A架构之应用架构 数字化转型-4A架构之数据架构 数字化转型-4A架构之技术架构 数据架构 Data Architecture&#xff08;DA&…