C++中是否有STL或Boost函数可获取已排序vector唯一元素的索引
已排序向量唯一元素索引的STL/Boost实现方案
首先明确结论:C++ STL和Boost都没有提供“一步到位直接返回唯一元素对应索引”的单独函数,但完全可以通过组合STL/Boost提供的成熟标准组件实现需求,不需要自行手写冗余的遍历判断逻辑,所有实现的时间复杂度和原生手写遍历完全一致,不存在额外的性能损耗。
唯一元素首次出现索引获取
STL提供的边界检测类算法是最适合的基础组件。这类算法本身的运行逻辑就是遍历已排序范围,识别所有连续重复元素的边界,其内置的遍历流程天然会经过每一个唯一元素的首次出现位置。
不需要额外二次遍历,只需要在算法识别到元素边界时,将当前迭代器与原向量起始位置的差值(即整数索引)存入结果集即可。如果不希望算法修改原向量内容,可以选用只读的std::adjacent_find逐次定位相邻不同元素的边界,对应实现如下:
#include <vector> #include <algorithm> #include <functional> // std::not_equal_to std::vector<int> get_first_occur_index(const std::vector<int>& v) { std::vector<int> res; if (v.empty()) return res; res.push_back(0); // 首元素的首次出现索引固定为0 auto curr = v.begin(); while (curr != v.end()) { // 定位到当前连续相等块的最后一个位置 curr = std::adjacent_find(curr, v.end(), std::not_equal_to<int>()); if (curr == v.end()) break; // 下一个唯一元素块的起点为当前位置的下一位 curr += 1; res.push_back(curr - v.begin()); // 迭代器转换为原向量的整数索引 } return res; }
针对给出的示例向量(注:示例代码中3,3,,4为笔误,不影响逻辑验证),该函数输出结果与预期的{0,3,7,9,10}完全匹配。
如果使用Boost生态,可搭配boost::adaptors::indexed直接获取带索引的迭代视图,省去手动计算迭代器差值的步骤,逻辑保持完全一致。
很多人误以为需要自己写循环逐次判断相邻元素的差异,实际上这些边界判断的逻辑STL早就提供了成熟的实现,只需要把边界位置转换成对应索引存储即可,完全不需要从零造轮子。
唯一元素最后一次出现索引获取
基于已经获取的所有唯一元素首次出现索引,可以非常低成本推导出对应的末次出现索引:
- 除最后一个唯一元素外,其余元素的最后出现位置,就是下一个唯一元素首次出现位置的前一位
- 最后一个唯一元素的最后出现位置,就是原向量最后一个元素的索引(即
v.size() - 1)
对应实现如下:
std::vector<int> get_last_occur_index(const std::vector<int>& v) { auto first_idx_list = get_first_occur_index(v); std::vector<int> res; for (int i = 0; i < first_idx_list.size(); ++i) { if (i < first_idx_list.size() - 1) { res.push_back(first_idx_list[i + 1] - 1); } else { res.push_back(v.size() - 1); } } return res; }
该函数的输出结果与预期的{2,6,8,9,15}完全一致,全程没有额外的全量扫描开销。
内容的提问来源于stack exchange,提问作者Shahgee
相关产品推荐
相关产品推荐

