std::set插入查重最直观,o(n log n)且代码简洁;unordered_set平均o(1)但需哈希支持;原地排序后线性扫描省空间o(1);unordered_map适合统计频次与定位位置;嵌套循环o(n²)应避免。

用 std::set 检查重复最直观
如果数组元素可比较(比如 int、string),直接往 std::set 里插,插失败就说明重复了。它底层是红黑树,插入 + 查重是 O(log n),整体 O(n log n),代码干净,不容易错。
- 每次插入前用
insert()返回的pair<iterator bool></iterator>判断:second为false表示已存在 - 别用
count()先查再插——多一次查找,纯浪费 -
std::unordered_set更快(平均O(1)),但需要哈希支持;内置类型没问题,自定义类型得自己写hash和==
原地排序后线性扫描更省空间
如果允许修改原数组,std::sort 后遍历相邻元素,只要 arr[i] == arr[i+1] 就找到重复。时间 O(n log n),空间 O(1)(不算排序栈开销),适合内存敏感场景。
- 注意:
std::sort要求迭代器支持随机访问,vector可以,list得换list::sort() - 对
int数组,std::sort通常比unordered_set实际更快(小数据量或缓存友好时) - 别漏边界检查——循环到
i ,否则访问越界
用 std::unordered_map 统计频次并定位重复位置
如果不仅要判断有没有重复,还要知道哪个值重复、重复几次、甚至第一次/最后一次出现位置,std::unordered_map<t int></t> 或 std::unordered_map<t vector>></t> 是更灵活的选择。
- 键存元素值,值存出现次数或下标列表;插入时更新即可
- 遇到次数从 1 变 2 的瞬间,就能立刻返回该元素和对应下标
- 注意:
unordered_map最坏情况退化成O(n)单次操作(哈希碰撞严重),但实际极少发生 - 如果只关心“是否存在”,用
unordered_set就够了,没必要多存计数
原始数组指针 + 手动嵌套循环的陷阱
新手常写两层 for:外层 i 从 0 到 n-1,内层 j 从 i+1 开始比较。逻辑没错,但时间复杂度 O(n²),10⁵ 元素就卡死,而且容易写错边界或漏掉 i+1 起始点。
- 内层循环必须从
i+1开始,否则每个元素会和自己比较,永远返回 true - 提前退出很重要:找到第一个重复就
return true,别傻跑完全部 - 仅适用于极小数组(
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











