直接调用std::set_intersection判断不相交效率低,因会完整构造交集;更优方案是手写双指针遍历(有序容器)或小集合转unordered_set后遍历查找(哈希容器),时间复杂度仍为O(m+n)但常数更小、可提前终止、无需额外内存。

用 std::set_intersection 判断是否不相交效率低吗?
直接调用 std::set_intersection 并检查结果为空,逻辑正确但浪费——它会实际构造交集,哪怕你只关心“有没有交集”。对两个大小为 m 和 n 的有序集合,时间复杂度仍是 O(m + n),但常数更大,且额外分配内存。
更轻量的做法是手写双指针遍历:利用 std::set(或已排序的 std::vector)的有序性,同步推进两个迭代器,一发现相等元素就立刻返回 false。
- 适用于
std::set、std::map键集,或任何已升序排列的容器 - 提前终止,最坏
O(m + n),最好O(1)(首元素就相等) - 无需额外空间,也不修改原容器
bool is_disjoint(const std::set<int>& a, const std::set<int>& b) {
auto it_a = a.begin(), it_b = b.begin();
while (it_a != a.end() && it_b != b.end()) {
if (*it_a == *it_b) return false;
if (*it_a < *it_b) ++it_a;
else ++it_b;
}
return true;
}
用 std::find_first_of 一行解决,但要注意什么?
std::find_first_of 看似简洁:std::find_first_of(a.begin(), a.end(), b.begin(), b.end()) == a.end(),但它对无序容器(如 std::unordered_set)才真正有意义;对 std::set 这类有序容器,它退化为 O(m × log n) 或更差(取决于实现),因为内部仍做线性扫描 + 查找。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 仅推荐用于
std::unordered_set与std::vector等混合场景 - 若
b是哈希表,std::find_first_of内部会遍历a,对每个元素查b,平均O(m) - 但若
a很大而b很小,不如把小集合转成unordered_set后遍历大集合
对 std::unordered_set,怎么避免 O(n²) 陷阱?
别用嵌套循环暴力判断——比如对 a 中每个元素调用 b.count() 是安全的,但若误写成 for (auto& x : a) for (auto& y : b) if (x == y) return false;,就掉进 O(|a| × |b|) 坑里了。
立即学习“C++免费学习笔记(深入)”;
- 正确做法:确保至少一个集合支持
O(1)查找,优先遍历较小集合 - 示例:
if (a.size() > b.size()) return is_disjoint(b, a); // 交换参数 -
std::unordered_set::count()平均O(1),最坏O(n)(哈希冲突严重时),但实践中足够快
bool is_disjoint(const std::unordered_set<int>& a, const std::unordered_set<int>& b) {
if (a.empty() || b.empty()) return true;
if (a.size() > b.size()) return is_disjoint(b, a);
for (const auto& x : a)
if (b.find(x) != b.end()) return false;
return true;
}
为什么不能直接用 std::includes?
std::includes(a, b) 检查的是 “a 是否包含 b 的所有元素”,不是不相交。有人误以为 !std::includes(a,b) && !std::includes(b,a) 能等价于不相交,这是错的:两个集合互不包含,但仍有公共元素(比如 a={1,2}, b={2,3}),此时 includes 全为 false,但它们显然相交。
-
std::includes解决的是子集问题,语义完全不同 - 即使容器有序,也不能复用它来判断 disjoint
- 混淆这两个概念会导致逻辑 bug,且不易通过测试用例暴露(边界 case 少)
includes 和暴力二重循环。

















