用std::unordered_map统计频次是最直接解法,遍历一次记录次数并动态更新最高频元素;元素范围小且非负时可用vector计数数组提升性能;需返回所有众数时应收集所有等于最大频次的键,并按需排序。

用 std::unordered_map 统计频次是最直接的解法
不需要排序,也不依赖元素范围,适用于任意可哈希类型(如 int、std::string)。核心逻辑就是遍历一次数组,用哈希表记录每个值出现的次数,再遍历哈希表找最大频次对应的键。
常见错误是只记最大次数却没保存对应元素,或者在频次相同时没明确“取第一个”还是“取任意一个”。实际中多数场景要的是「首次达到最高频次的那个元素」,所以建议边统计边更新结果:
int findMostFrequent(const std::vector<int>& arr) {
if (arr.empty()) throw std::runtime_error("empty array");
std::unordered_map<int, int> count;
int result = arr[0], maxCount = 0;
for (int x : arr) {
count[x]++;
if (count[x] > maxCount) {
maxCount = count[x];
result = x;
}
}
return result;
}
数组元素范围小且为非负整数时,用 std::vector 当计数数组更高效
比如题目限定元素在 [0, 1000] 内,直接开个大小为 1001 的 std::vector<int>,下标即数值,省去哈希计算开销。空间换时间,实测比 unordered_map 快 2–3 倍(尤其数据量大时)。
注意两个坑:
立即学习“C++免费学习笔记(深入)”;
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 必须确认元素最小值是否为 0;若含负数,得整体偏移(如加
offset = -min_val),否则越界 - 数组大小不能硬写死,应根据实际数据范围动态确定,避免栈溢出或内存浪费
需要返回所有众数(多个元素并列最高频次)时,不能只存一个 result
原逻辑里用 if (count[x] > maxCount) 是严格大于,自然只保留最后一个达到新高的元素。但若要所有众数,得改成 if (count[x] >= maxCount) 并配合清空/追加逻辑:
std::vector<int> findAllModes(const std::vector<int>& arr) {
std::unordered_map<int, int> count;
for (int x : arr) count[x]++;
int maxCount = 0;
for (const auto& p : count) maxCount = std::max(maxCount, p.second);
std::vector<int> modes;
for (const auto& p : count)
if (p.second == maxCount) modes.push_back(p.first);
return modes;
}
这里没做排序,返回顺序取决于哈希表遍历顺序——C++20 起 unordered_map 遍历不保证稳定,如需固定顺序(比如按数值升序),得额外对 modes 调用 std::sort。
用 std::nth_element 或排序求众数?通常没必要
有人想先排序再线性扫描找最长连续段,时间复杂度 O(n log n),比哈希方案慢;而且破坏原数组顺序,若需保持索引位置就更麻烦。只有当你**已经排好序**或**必须用 O(1) 额外空间**(且允许修改原数组)时才考虑。
真要这么做,注意边界判断:单元素数组、全相同元素、最后几个元素构成最长段等情况,循环结束时容易漏判最后一段。
真正容易被忽略的是:当数组为空或只含一个元素时,所有方案都要显式处理,否则访问 arr[0] 或遍历空 unordered_map 会出错。别指望编译器帮你兜底。

















