std::set_intersection要求两输入范围必须升序排列,否则结果不可预测;未排序时推荐用unordered_set实现o(n+m)交集,或用map统计频次处理重复元素。

用 std::set_intersection 前必须排序
这个函数本身不处理无序数据,只做“归并式交集”,输入的两个范围都得是升序排列的,否则结果不可预测。常见错误是直接传入原始数组,得到空结果或乱序片段。
- 先对两个数组分别调用
std::sort(注意:会改变原顺序) - 或者用
std::vector+std::sort+std::unique预处理去重再排序 - 目标容器(如
std::vector)需预留足够空间,或用std::back_inserter
用 std::unordered_set 实现 O(n+m) 交集
当数组未排序、且不关心结果顺序时,这是更自然的选择——时间复杂度低,代码直白,还不修改原数据。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 把第一个数组所有元素插入
std::unordered_set - 遍历第二个数组,对每个元素检查是否在集合中,存在就加入结果容器
- 注意:重复元素会被自动去重;若需保留重复(如 A 有 2 个 5,B 有 1 个 5,只取 1 个),就得改用
std::unordered_map记频次
处理重复元素的常见陷阱
std::set_intersection 默认按值匹配,但不会“消耗”元素——比如 A = {1,1,2}, B = {1,2,2},结果是 {1,2},不是 {1,1,2,2}。它本质是“有序集合交集”,不是“多重集合交集”。
- 要实现“最小频次交集”(即每个数出现 min(countA, countB) 次),得用
std::map或std::unordered_map分别统计频次,再遍历一个 map 取较小值 - 别用
std::set替代std::unordered_set做哈希交集——除非你明确需要排序结果,否则纯属性能浪费 - 如果数组含自定义类型,
std::set_intersection要求提供严格弱序比较;而unordered_set要求定义hash和operator==
完整可运行的小例子(unordered_set 版)
#include <vector>
#include <unordered_set>
#include <iostream>
std::vector<int> intersect(const std::vector<int>& a, const std::vector<int>& b) {
std::unordered_set<int> set_a(a.begin(), a.end());
std::vector<int> result;
for (int x : b) {
if (set_a.count(x)) {
result.push_back(x);
set_a.erase(x); // 防止重复添加(单次匹配)
}
}
return result;
}
</int></int></int></int></int></iostream></unordered_set></vector>
这个版本保证每个交集元素最多出现一次,且不依赖排序。真正麻烦的地方往往不在算法选择,而在要不要去重、要不要保序、要不要保留原始频次——这些得看业务场景定,不能套模板。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










