news 2026/4/16 11:56:41

力扣169:多数元素-抵消法和哈希表

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
力扣169:多数元素-抵消法和哈希表

题目描述

给定一个大小为 n 的数组 nums,返回其中的多数元素。多数元素是指在数组中出现次数大于 ⌊n/2⌋ 的元素。你可以假设数组是非空的,并且给定的数组总是存在多数元素。

方法一:摩尔投票法(最优解)

核心思想

这个算法基于一个关键的抵消思想:由于多数元素的数量超过总数的一半,那么多数元素与其他元素一一抵消后,最后剩下的必然是多数元素。

算法步骤

  1. 初始化候选元素candidate和计数器count为 0

  2. 遍历数组中的每个元素:

    • 如果count为 0,将当前元素设为候选元素

    • 如果当前元素等于候选元素,count加 1

    • 如果当前元素不等于候选元素,count减 1

  3. 遍历结束后,候选元素就是多数元素

代码实现

class Solution { public int majorityElement(int[] nums) { int ans = 0; // 存储当前候选的多数元素 int hp = 0; // 计数器,表示当前候选元素的"生命值" for (int x : nums) { if (hp == 0) { // 生命值为0,需要新的候选 ans = x; // 设置x为新的候选元素 hp = 1; // 初始生命值为1 } else { // 已经有候选元素 if (ans == x) { // 如果当前元素和候选相同 hp += 1; // 生命值+1(支持者增加) } else { // 如果当前元素和候选不同 hp -= 1; // 生命值-1(相互抵消) } } } return ans; // 最终剩下的候选就是多数元素 } }
//简化 class Solution { public int majorityElement(int[] nums) { int ans = 0; int hp = 0; for (int num : nums) { if (hp == 0) { ans = num; } count += (num == ans) ? 1 : -1; } return ans; } }

复杂度分析

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

  • 空间复杂度:O(1),只使用了常数级别的额外空间

算法优势

这是解决多数元素问题的最优算法,特别适合空间要求严格的场景。它巧妙地将问题转化为"擂台比武",每个元素要么支持当前候选(同门师兄弟),要么反对(敌人),最终多数元素会胜出。

方法二:哈希表法(最直观)

核心思想

使用哈希表记录每个元素出现的次数,然后找到出现次数超过一半的元素。这是最直观的解法,也是面试中最容易想到的方法。

算法步骤

  1. 创建一个哈希表来记录每个数字出现的次数

  2. 遍历数组,更新哈希表中每个数字的计数

  3. 遍历哈希表,找到出现次数超过 n/2 的元素

代码实现

class Solution { public int majorityElement(int[] nums) { // 创建哈希表 Map<Integer, Integer> countMap = new HashMap<>(); // 统计每个数字出现的次数 for (int num : nums) { countMap.put(num, countMap.getOrDefault(num, 0) + 1); // 可以在统计过程中直接判断,提高效率 if (countMap.get(num) > nums.length / 2) { return num; } } // 理论上不会执行到这里 return -1; } }

简化版本

class Solution { public int majorityElement(int[] nums) { Map<Integer, Integer> map = new HashMap<>(); int maxCount = 0; int result = 0; for (int num : nums) { int count = map.getOrDefault(num, 0) + 1; map.put(num, count); // 在遍历过程中更新最大值 if (count > maxCount) { maxCount = count; result = num; } } return result; } }

复杂度分析

  • 时间复杂度:O(n),需要遍历一次数组,哈希表操作平均O(1)

  • 空间复杂度:O(k),其中k是数组中不同元素的数量,最坏情况下为O(n)

方法对比与选择建议

特性Boyer-Moore算法哈希表统计法
时间复杂度O(n)O(n)
空间复杂度O(1)O(n)
实现难度中等(需要理解算法原理)简单(直观易懂)
是否需要验证需要(如果不确定存在多数元素)不需要(遍历时即可判断)
实际性能更快(常数时间小)稍慢(哈希表操作有开销)
适用场景空间限制严格时代码可读性优先时

选择建议

  1. 面试场景:先讲解Boyer-Moore算法,展示算法优化思想

  2. 实际工作:如果对空间要求不高,使用哈希表法更稳妥

  3. 比赛/刷题:追求极致性能用Boyer-Moore,追求快速实现用哈希表

常见变种问题

1. 寻找出现次数超过 n/3 的元素

class Solution { public List<Integer> majorityElement(int[] nums) { // 最多有两个这样的元素 List<Integer> result = new ArrayList<>(); // 使用Boyer-Moore算法的扩展版本 int candidate1 = 0, candidate2 = 0; int count1 = 0, count2 = 0; for (int num : nums) { if (num == candidate1) { count1++; } else if (num == candidate2) { count2++; } else if (count1 == 0) { candidate1 = num; count1 = 1; } else if (count2 == 0) { candidate2 = num; count2 = 1; } else { count1--; count2--; } } // 验证候选元素是否真的超过n/3 count1 = 0; count2 = 0; for (int num : nums) { if (num == candidate1) count1++; else if (num == candidate2) count2++; } if (count1 > nums.length / 3) result.add(candidate1); if (count2 > nums.length / 3) result.add(candidate2); return result; } }

2. 寻找出现次数最多的元素(众数)

class Solution { public int majorityElement(int[] nums) { // 使用哈希表统计频率 Map<Integer, Integer> countMap = new HashMap<>(); int maxCount = 0; int result = nums[0]; for (int num : nums) { int count = countMap.getOrDefault(num, 0) + 1; countMap.put(num, count); if (count > maxCount) { maxCount = count; result = num; } } return result; } }

总结

多数元素问题是一个经典的算法问题,展示了不同解法之间的权衡:

  1. Boyer-Moore投票算法是空间最优解,体现了算法设计的巧妙性

  2. 哈希表统计法是最直观的解,易于理解和实现

  3. 排序法虽然简单,但时间复杂度较高

  4. 分治法展示了递归解决问题的思路

在实际应用中,根据具体需求选择合适的解法。如果空间限制严格,Boyer-Moore算法是最佳选择;如果追求代码可读性和维护性,哈希表法更合适。无论选择哪种方法,理解其背后的原理和适用场景才是最重要的。

刷题建议:掌握Boyer-Moore算法的思想和实现,这在面试中经常被考察。同时也要熟悉哈希表解法,因为它适用于更广泛的统计问题。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 11:19:39

STL专项:queue 队列

queue queue 提供了先进先出&#xff08;First In First Out&#xff09;的数据结构。队列在尾部添加元素&#xff0c;在头部删除元素。 常见的应用有&#xff1a;模拟、约瑟夫环、bfs、分支限界搜索、单调队列等算法。 创建队列 queue<int> q; //创建一个 int 类…

作者头像 李华
网站建设 2026/4/15 13:11:05

给老公改个嘎嘎甜的备注

干饭一级选手&#x1f35a; 家庭ATM机&#x1f4b8;剩饭处理器♻️ 专属抬杠员&#x1f645;沙发黏人精&#x1f6cb;️ 摸鱼总指挥&#x1f41f;零食小偷小摸&#x1f35f; 憨憨显眼包&#x1f61c;起床困难户&#x1f634; 废话输出机&#x1f4ac;家务甩锅王&#x1f373; 快…

作者头像 李华
网站建设 2026/4/13 12:13:27

YOLO与Crossplane跨云平台集成:统一资源编排

YOLO与Crossplane跨云平台集成&#xff1a;统一资源编排 在智能制造工厂的监控中心&#xff0c;一台部署在 AWS 上的摄像头突然检测到传送带异常&#xff0c;系统毫秒级触发告警。与此同时&#xff0c;位于 Azure 上的备用推理节点已自动启动并接管任务——这一切的背后&#…

作者头像 李华
网站建设 2026/4/14 11:04:04

hello-agents 学习笔记:解锁智能体三大经典范式,从原理到实战

在上一章吃透大语言模型的核心逻辑后&#xff0c;终于迎来了最令人兴奋的实战环节 —— 亲手构建智能体。如果说大语言模型是智能体的 "大脑"&#xff0c;那这些经典范式就是让大脑学会 "思考与行动" 的行为准则。市面上早已不乏 LangChain、LlamaIndex 这…

作者头像 李华
网站建设 2026/4/2 1:08:36

在微网的世界里,电能共享是个大话题。今天咱们聊聊如何用非对称纳什谈判来优化多微网间的电能共享,顺便加点代码,让大家感受一下这个高级玩意儿

基于非对称纳什谈判的多微网电能共享运行优化策略 关键词&#xff1a;纳什谈判 合作博弈 微网 电转气-碳捕集 P2P电能交易交易 参考文档&#xff1a;《基于非对称纳什谈判的多微网电能共享运行优化策略》完美复现 仿真平台&#xff1a;MATLAB CPLEXMOSEK/IPOPT 主要内容&…

作者头像 李华
网站建设 2026/4/14 20:30:39

YOLO模型灰度版本灰度结束后的用户通知

YOLO模型灰度版本结束后的用户通知机制解析 在智能制造产线高速运转的车间里&#xff0c;一台搭载YOLOv8的视觉检测设备正以每秒百帧的速度扫描着流水线上的电子元件。突然&#xff0c;系统后台触发了一条全量上线通知&#xff1a;“新版目标检测模型已完成验证&#xff0c;正式…

作者头像 李华