优先将原生数组转为std::vector或传入size参数;查找连续相同子序列应使用双指针法,外层i定起点、内层j拓展至值变化,若j-i≥2则记录(i,j-i)并令i=j跳过已处理段,避免重复计算。

用 std::vector 配合双指针遍历最直接
原生 C++ 数组不带长度信息,容易越界或漏判,实际开发中优先转成 std::vector 或传入明确的 size 参数。查找连续相同子序列(比如 {3,3,3} 在 {1,3,3,3,2} 中)本质是找最长连续重复段的起始和长度,双指针法清晰且无额外空间开销。
关键点:不是找“任意重复值”,而是找“连续、相同、长度 ≥ 2”的片段;单个元素不算“子序列”(按常规理解,“序列”隐含多元素)。
- 外层用
i指向当前候选起点,内层用j向后拓展直到arr[j] != arr[i] - 若
j - i >= 2,说明从i开始有一段长度至少为 2 的连续相同子序列 - 别忘了让
i直接跳到j,避免重复计算(例如{2,2,2}:找到[0,2]后,i应设为3,而非1)
std::adjacent_find 只能找首对相邻相等元素
std::adjacent_find 是标准库里最接近的工具,但它只返回**第一对相邻相等元素的首位置**,比如对 {1,2,2,2,3} 返回迭代器指向第一个 2,无法直接知道后面还有几个 2。它适合“是否存在重复相邻”,不适合“找完整连续段”。
如果硬要用,得配合后续手动计数:
auto it = std::adjacent_find(vec.begin(), vec.end());
if (it != vec.end()) {
int val = *it;
auto end_it = std::find_if_not(it, vec.end(), [val](int x) { return x == val; });
int len = std::distance(it, end_it); // 这才是真实长度
}
但这样写反而比双指针啰嗦,还多一次函数调用开销。
手写循环时最容易错的三个边界
纯 C 风格数组(int arr[])下,下标越界和长度误判是高频问题:
- 忘记检查
i + 1 就访问 <code>arr[i+1]→ 触发未定义行为,尤其在n == 0或1时崩溃 - 把“连续相同长度”和“出现次数”混淆:比如
{1,1,2,2,2}中,2的连续长度是3,但总出现次数是3;而1连续长度是2,总次数也是2—— 两者仅在无间隔时才相等 - 结果存储时用
std::pair<int int></int>存{start, length},但后续遍历时又当成{start, end}用,导致偏移错误
需要返回所有匹配段?用 std::vector<:pair>></:pair> 收集
如果输入是 std::vector<int> v = {1,1,1,2,2,3,3,3,3}</int>,要找出所有连续 ≥2 的段,结构上推荐返回 std::vector<:pair int>></:pair>,其中 .first 是起始索引,.second 是长度。
示例逻辑片段:
std::vector<:pair int>> result;
for (int i = 0; i = 2) {
result.emplace_back(i, j - i);
}
i = j; // 跳过整个相同段
}</:pair>
注意:不要用 push_back({i, j-i}),在老编译器上可能推导失败;emplace_back 更稳妥。
连续相同子序列的“连续”二字是铁律——中间断开就重算,这点在处理浮点数组或自定义对象时,== 的语义是否合理也得同步检查。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











