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

算法训练营第十二天| 169.多数元素

今日任务:169. 多数元素 尝试多种解法,提交第二周学习小结
题意:
给定一个大小为 n 的数组 nums ,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。

你可以假设数组是非空的,并且给定的数组总是存在多数元素。
题目链接:https://leetcode.cn/problems/majority-element/
官方题解:https://leetcode.cn/problems/majority-element/solutions/146074/duo-shu-yuan-su-by-leetcode-solution/

思路:

一、基础思路

1. 哈希表统计法(最直观)

核心思想:遍历数组,用哈希表记录每个数字出现的次数,最后遍历哈希表,找到次数超过 n/2 的数字。

  • 时间复杂度:O (n)(遍历两次数组)
  • 空间复杂度:O (n)(需要哈希表存储元素)
  • 优点:逻辑简单,一眼能看懂
  • 缺点:占用额外空间,不满足进阶要求

2. 排序法(取巧简单)

核心思想:数组排序后,多数元素一定出现在数组中间位置(因为它超过一半长度)。比如数组长度 7,中间索引 3;长度 3,中间索引 1,排序后这个位置的数就是答案。

  • 时间复杂度:O (n log n)(排序的时间)
  • 空间复杂度:O (1) 或 O (n)(取决于排序算法)
  • 优点:代码极简,一行排序 + 取中间值
  • 缺点:时间复杂度不如最优解

二、进阶最优思路(满足 O (n) 时间 + O (1) 空间)

摩尔投票法(本题最佳解法)

核心思想:利用「多数元素数量 > 其他所有元素总和」的特性,通过投票抵消找到目标数。

  1. 初始化两个变量:候选人(candidate)票数(count),初始值都为 0
  2. 遍历数组每个元素:
    • 如果票数count=0,把当前元素设为新候选人
    • 如果当前元素 == 候选人,票数 + 1
    • 如果当前元素!= 候选人,票数 - 1
  3. 遍历结束后,候选人就是多数元素

原理:多数元素的数量足够多,抵消完其他元素后,最终剩下的一定是它。


三、代码实现(最优:摩尔投票法)

def majorityElement(nums): # 初始化候选人和票数 candidate = 0 count = 0 for num in nums: # 票数为0,更换候选人 if count == 0: candidate = num # 投票:相同+1,不同-1 count += 1 if num == candidate else -1 return candidate

遇到的困难:

一、做题第一想法的阻碍

  1. 只会暴力思路一开始只能想到双层循环逐个统计次数,时间复杂度爆炸,完全没考虑数据范围(数组长度最大 5e4),暴力解法直接超时。

  2. 想不到哈希优化知道要统计次数,但想不到用字典 / 哈希表快速计数,只会手写统计,代码冗余、效率低。


二、普通解法的困难(哈希 / 排序)

  1. 哈希表细节易错
  • 忘记初始化键值,导致 key 不存在报错;
  • 遍历完字典后,不会快速筛选出「大于 n/2」的元素,判断条件写错。
  1. 排序法理解卡顿不能理解:为什么排序后中间下标一定是多数元素,逻辑想不通,只能死记结论,换题型就不会用。

三、进阶最大难点:摩尔投票法(最容易卡)

  1. 完全理解不了核心原理不懂「相互抵消」的逻辑,不明白为什么两两不同元素抵消,最后剩下的一定是众数。疑惑点:为什么别的元素不会残留?

  2. 流程逻辑混乱记不住执行步骤:count 为 0 才换候选人、相同 + 1、不同 - 1,手写代码时顺序写反、条件写错。

  3. 边界场景怀疑遇到负数、超长数组时,会怀疑算法失效,不敢确定结果一定正确。


四、通用代码层面困难

  1. 下标、长度计算错误混淆n/2⌊n/2⌋,判断次数的条件写错。
  2. 忽略题目条件题目明确:一定存在多数元素,不需要额外校验,自己多写多余判断,增加代码负担。

五、整体思维困难

  1. 思维固化只会用「计数类」常规思路,缺少抵消、博弈、投票这类巧解思维,算法思维单一。
  2. 不会分析复杂度写完代码后,不会判断时间、空间复杂度,不知道哪种解法符合进阶要求。

(摩尔投票法)

int majorityElement(int* nums, int numsSize) { // 候选人 int candidate = 0; // 票数 int count = 0; for (int i = 0; i < numsSize; i++) { // 票数为0,更换候选人 if (count == 0) { candidate = nums[i]; } // 相同+1,不同-1 if (nums[i] == candidate) { count++; } else { count--; } } // 题目保证一定存在多数元素,直接返回 return candidate; }

今日收获:

  • 掌握了多数元素问题的核心题意,明确多数元素是出现次数大于数组一半长度的元素,且题目保证答案一定存在。
  • 学习并理解摩尔投票法的核心原理,依靠元素相互抵消的思想,巧妙找出目标值,打破了只会暴力统计、哈希计数的固定思维。
  • 能够独立读懂、编写该题的 C 语言摩尔投票法代码,熟练掌握候选人、计数变量的逻辑操作,实现 O (n) 时间、O (1) 空间的高效解法。
  • 认识到不同算法的复杂度差异,学会区分常规解法与进阶最优解法,提升了算法优化的思维。
  • 梳理了做题时容易出现的思路卡点与逻辑误区,为后续同类巧解类算法题目积累了解题经验。
http://www.jsqmd.com/news/698739/

相关文章:

  • 如何用Fay数字人框架3步打造你的智能虚拟助手:从零到一的实践指南
  • 广州值得信赖的靠谱除甲醛机构 TOP5 推荐 - GrowthUME
  • 智能基线校正终极指南:如何用airPLS算法解决光谱分析中的基线漂移问题
  • 慧科讯业:2026年北京车展前瞻报告
  • 2026年天津新能源汽车推荐去哪里买?101汽车文化广场一站式体验深度指南 - 优质企业观察收录
  • 开源音乐格式转换工具实战:5步解锁网易云音乐加密文件
  • 3分钟掌握机构级金融数据:Finnhub Python客户端的终极指南
  • jcifs-ng终极指南:5分钟掌握Java SMB客户端开发
  • 把数百个软件包迁移到 ARM64,Cloudflare 踩了哪些坑
  • 【Kubernetes专项】温故而知新,重温技术原理(1)
  • Ubuntu 22.04 系统上完整安装 ROS 2 Humble
  • 告别Express?用Hono在Cloudflare Workers上5分钟搭建一个超快API
  • 2026年天津新能源汽车推荐去哪里买?101汽车文化广场一站式选车体验深度评测 - 优质企业观察收录
  • 苹果触控板在Windows上的完美重生:mac-precision-touchpad开源驱动深度解析
  • 缠论分析太复杂?ChanlunX:3分钟让你从新手变高手!
  • 终极指南:Switch大气层系统1.7.1完整安装与功能解锁
  • 基于SSH的多跳远程访问工具PKURemote:原理、实现与配置管理
  • Klipper共振补偿:彻底解决3D打印“幽灵纹路“的专业指南
  • D6.2.熟练使用kubernetes的高级调度策略实战(nodeSelector、Pod亲和反亲和、污点及容忍)
  • 2026年天津新能源汽车推荐去哪里?101汽车文化广场一站式选购指南 - 优质企业观察收录
  • 3分钟精通TrollInstallerX:iOS 14-16.6.1设备安全安装TrollStore终极指南
  • InkOS:基于多Agent协作与长期记忆的AI小说创作系统深度解析
  • real-anime-z创意拓展:结合‘雨景’‘霓虹’‘樱花’等氛围词激发新构图
  • Botty:暗黑2重制版自动化助手,解放双手的智能刷宝方案
  • 从 IP 包到 HTTP 请求,Cloudflare 的 Oxy 代理框架是怎么做到
  • 终极指南:让Apple触控板在Windows上完美运行
  • 别再手动抄数据了!手把手教你用WinCC用户归档+SQL Server自动生成报表(附VBS脚本)
  • 以太网端口的ESD防护器件选型
  • 三步快速对接 gpt-image-2 图像生成 API 教程
  • Windows 11上Autopsy 4.19.3性能调优实战:从卡顿到流畅,我调整了这两个关键设置