查找std::set中小于给定键的最大元素的更优实现方案咨询
find_less 函数的最优实现方案
你当前写的find_less已经是std::set场景下时间复杂度最优、逻辑最严谨的实现,没有更优的写法了。原因如下:
- 完全复用了set成员函数
lower_bound的O(logn)对数复杂度,没有额外性能开销 - 边界判断逻辑完备:当容器内所有元素都大于等于目标值时,直接返回
set.end(),完全符合「找小于目标值的最后一个元素,不存在则返回尾后迭代器」的语义 - 相比用反向迭代器调用通用
std::lower_bound的写法,既避免了O(n)的性能退化,也省去了反向迭代器转正向迭代器的冗余操作
如果需要实现「查找小于等于目标值的最后一个元素」,只要把lower_bound替换为upper_bound即可,逻辑完全一致:
Set::iterator find_less_or_equal(int val) { auto i = set.upper_bound(val); if (i == set.begin()) { return set.end(); } return --i; }
为什么std::set没有内置小于/小于等于的查找接口
这个设计并不反常,属于标准库的常规接口设计思路:用最少的原子接口覆盖全场景需求。lower_bound(找第一个>=目标的元素)和upper_bound(找第一个>目标的元素)已经是最底层的原子查找接口,所有其他查找需求(小于、小于等于、大于、大于等于的首个/末尾元素)都可以通过这两个接口的结果搭配迭代器移动快速实现,标准库不需要额外新增冗余的内置接口增加维护成本。
你提到的std::lower_bound(set.rbegin(), set.rend(), val)写法确实不推荐,因为std::set的迭代器是双向迭代器,不是随机访问迭代器,通用版本的std::lower_bound对双向迭代器只能达到O(n)的线性时间复杂度,性能远低于set成员函数的O(logn)对数复杂度。
内容的提问来源于stack exchange,提问作者Dmitriano
相关产品推荐
相关产品推荐

