计数数组法可在O(n)时间内找出众数,适用于值域集中且可控的整型数组;通过映射元素到索引累加频次,再扫描计数数组获取最大频次对应值,支持负数偏移与多众数扩展。

在 Java 中,若数组元素范围已知且较集中(如非负整数、取值在 [0, k] 之间),可借助计数数组(count array)在 O(n) 时间内找出众数(出现次数最多的元素)。该方法本质是空间换时间,避免排序或哈希表的常数开销,适合整型数组且值域可控的场景。
适用前提:明确值域范围
计数数组法要求能预估数组中元素的最小值和最大值。最常见的是元素为非负整数且最大值不超过某个合理上限(例如 ≤ 10⁵)。若值域过大(如 int 范围全量)或含负数/浮点数,则需先离散化或改用 HashMap。
- 若所有元素 ∈ [min, max],则申请长度为 max - min + 1 的 int 数组
- 遍历原数组时,将每个元素
x映射到索引x - min处进行累加 - 最后扫描计数数组,找到最大计数值对应的索引,再还原为原始值
核心实现步骤(含边界处理)
以非负整数为例(min = 0),假设输入数组为 int[] nums:
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
- 先遍历一次,获取最大值
maxVal,确定计数数组长度:new int[maxVal + 1] - 第二次遍历
nums,对每个num执行:count[num]++ - 第三次遍历
count数组,记录最大频次及其下标:if (count[i] > maxCount) { maxCount = count[i]; mode = i; } - 返回
mode即为众数(若多个元素并列最多,此法默认返回值最小的那个;如需全部众数,可额外收集)
处理负数与多众数的扩展方式
若数组含负数,例如范围在 [-50, 50],可统一偏移:令 offset = 50,则索引映射为 num + offset,计数数组长度为 101。若需返回所有众数,不提前终止,而是在第三步中维护一个 List<integer></integer>,每当 count[i] == maxCount 时加入,遇到更大值则清空并更新。
立即学习“Java免费学习笔记(深入)”;
对比其他方法的取舍
排序法(O(n log n))或 HashMap(平均 O(n),但有哈希计算与扩容开销)更通用;而计数数组法在满足值域约束时,真正严格线性、无装箱、缓存友好。实际编码中,建议先校验数据分布——若最大值远超数组长度(如 [0, 10⁶] 中仅 100 个数),空间浪费大,此时 HashMap 更稳妥。

















