单次遍历统计连续1长度的核心是边扫描边计数,遇1累加、遇0更新max_len并重置,循环后必须再比较一次current_len与max_len,否则结尾连续1会被忽略。

用单次遍历统计连续1的长度
核心思路是边扫描边计数,遇到1就累加当前长度,遇到0就重置。不需要额外空间,时间复杂度稳定为 O(n),比反复调用 std::find 或嵌套循环高效得多。
常见错误是把重置逻辑写在循环末尾,导致末尾连续1段没被比较;或者漏掉数组全为1的边界情况。
- 初始化两个变量:
current_len = 0(当前连续1长度)、max_len = 0(历史最大值) - 遍历数组每个元素
arr[i]:若为1,current_len++;若为0,用std::max(max_len, current_len)更新最大值,再将current_len置0 - 循环结束后必须再比较一次:
max_len = std::max(max_len, current_len),否则结尾连续1会被忽略
处理 std::vector<int></int> 和原生数组时的差异
两者遍历方式一致,但获取长度的方法不同,容易混淆导致越界或编译失败。
- 对
std::vector<int></int>,用v.size();对 C 风格数组(如int arr[10]),不能直接用sizeof(arr),必须传入长度参数或用std::size(arr)(C++17 起) - 若函数参数是
int* arr,必须额外传入size_t n,否则无法安全遍历 - 使用
auto& x : vec范围 for 循环时,注意x是引用还是值拷贝——这里只需读取,用const auto& x或直接int x都可
遇到 std::string 类型输入怎么办
很多题目给的是 "101110" 这样的字符串,不是整数数组。直接按字符比较即可,但别忘了字符 '1' 不等于整数 1。
- 判断条件应为
s[i] == '1',不是s[i] == 1 - 如果字符串含非法字符(如空格、'0'/'1'以外),建议先用
std::all_of(s.begin(), s.end(), [](char c){ return c == '0' || c == '1'; })校验 - 性能上,
std::string遍历和 vector 几乎无差别,无需转成 int 数组
为什么不用 std::max_element 或 STL 算法组合
因为没有现成的“最长连续子段”算法。试图用 std::adjacent_find 或 std::partition 反而更绕,且难以正确维护区间长度。
-
std::max_element找的是最大值,不是最长连续段 - 想用
std::accumulate实现状态转移也可以,但可读性差,且需传入自定义二元操作,容易写错初始值和折叠逻辑 - 实测在 10⁶ 规模下,手写单循环比任何 STL 组合快 1.5–2 倍,关键在于避免迭代器多次解引用和函数对象调用开销
实际写的时候,最易被忽略的是结尾那段连续1的更新——哪怕只漏一行 max_len = std::max(max_len, current_len),就会在输入 {1,1,1} 时返回0。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











