:双指针线性扫描求最长连续 1 段)
教程文档【免费下载链接】LogicStack-LeetCode公众号「宫水三叶的刷题日记」刷穿 LeetCode 系列文章源码项目地址https://gitcode.com/gh_mirrors/lo/LogicStack-LeetCode点击查看免费下载导读本文基于「宫水三叶的刷题日记」刷穿 LeetCode 系列的第 485 篇题解完整讲解 LeetCode 485「最大连续 1 的个数」这道高频简单题给定一个只包含 0 和 1 的二进制数组如何用 O(n) 时间、O(1) 空间求出最长连续 1 段的长度。全文从暴力思路出发逐步收敛到双指针扫描的核心思想并给出 Java、C、Python、TypeScript 四种可直接提交的完整实现最后结合仓库中同构的延伸题目如 1446. 连续字符、2760. 最长奇偶子数组、1004. 最大连续1的个数 III说明这套「找最远合法右端点并整体跳转」的双指针范式可以如何迁移复用。一、题目描述与约束原题文档位于仓库的 485. 最大连续 1 的个数简单.md题目本身非常简洁给定一个二进制数组计算其中最大连续 1 的个数。示例输入[1,1,0,1,1,1] 输出3 解释开头的两位和最后的三位都是连续 1 所以最大连续 1 的个数是 3。题目的约束条件有两个它们直接决定了算法的选择空间输入的数组只包含0和1输入数组的长度是正整数且不超过 $10^4$。因为数组元素只有 0/1 两种取值、长度上限也只有 $10^4$这道题的算法空间很宽松。但作为双指针入门题它的价值在于让读者掌握「如何把连续段整体处理、如何跳过必然不优的候选起点」这也是它在系列中被归类为 Tag「双指针」的原因——该归类可对照仓库的 双指针题单 查看其中收录了包括 485 在内的数十道双指针题目及对应题解链接。二、思路推导从暴力枚举到双指针2.1 暴力做法最朴素的想法是枚举每一个可能的起点再向后扩展统计连续 1 的长度外层循环枚举左端点i内层循环从i开始向右只要nums[j] 1就一直累加长度每次把当前段长度与全局答案ans取最大值。暴力做法的时间复杂度为 O(n²)最坏情况如数组全为 1下会枚举出 O(n²) 个候选段。虽然本题 $n \le 10^4$ 勉强可行但完全没有必要——因为其中大量候选段是「必不可能是最长」的可以被整体跳过。2.2 双指针的核心观察原文档给出的双指针解法建立在这样一个观察上对于一个确定的左端点l如果它是 1那么以它开头的最长连续 1 段其右边界是唯一确定的——即向右扫描遇到的第一个 0或数组越界。设r为这个最远右边界则[l, r)区间内全是 1段长度为r - l。此时可以断言以[l 1, r]中任意位置k作为左端点都不需要再检查。原因是从k出发的连续 1 段其右边界不可能越过r因为nums[r]是 0 或越界任何以k为起点的连续 1 段都会被r位置的 0 截断因此任何这类段的长度至多为r - k r - l必然不大于已经得到的r - l。因此扫描流程可以设计为令l从数组头开始扫描若nums[l] 0说明它不可能是连续 1 段的开头l直接右移跳过若nums[l] 1令r l向右找到第一个不满足「r在界内且nums[r] 1」的位置此时[l, r)全为 1长度r - l更新ans令l r 1从该位置继续处理r位置本身是 0 或越界不可能作为新段的开头。这样每个位置最多被l和r各访问常数次整个扫描是严格线性的 O(n)。三、四种语言的完整实现原文档为这道题提供了 Java、C、Python、TypeScript 四种可直接提交的实现以下代码完整保留原文档写法。Javaclass Solution { public int findMaxConsecutiveOnes(int[] nums) { int n nums.length, ans 0; for (int l 0; l n; ) { if (nums[l] 0 l 0) continue; int r l; while (r n nums[r] 1) r; ans Math.max(ans, r - l); l r 1; } return ans; } }Cclass Solution { public: int findMaxConsecutiveOnes(vectorint nums) { int n nums.size(), ans 0; for (int l 0; l n;) { if (nums[l] 0 l n) continue; int r l; while (r n nums[r] 1) r; ans max(ans, r - l); l r 1; } return ans; } };Pythonclass Solution: def findMaxConsecutiveOnes(self, nums: List[int]) - int: n, ans len(nums), 0 l, r 0, 0 while l n: if nums[l] 0: l 1 continue r l while r n and nums[r] 1: r 1 ans max(ans, r - l) l r 1 return ansTypeScriptfunction findMaxConsecutiveOnes(nums: number[]): number { let n nums.length, ans 0; for (let l 0, r 0; l n; ) { if (nums[l] 0 l 0) continue; r l; while (r n nums[r] 1) r; ans Math.max(ans, r - l); l r 1; } return ans; };四、代码细节解读边界安全与跳转逻辑这几段代码里有几处值得展开的细节理解它们能避免在真实提交时踩坑if (nums[l] 0 l 0) continue;Java/TypeScript 版由于l始终是非负整数l 0恒为真所以这行的实际效果等价于「l先自增然后continue回到循环条件判断」。当l恰好是最后一个元素且为 0 时l后l n外层for条件l n直接判假退出不会发生越界访问。if (nums[l] 0 l n) continue;C 版写法略有差异多带了一个界内判断。当nums[l] 0且l后仍小于n时继续循环若l后l n即最后一个元素是 0则不continue而是进入下面的逻辑——此时r l且l nwhile (r n nums[r] 1)因为r n不成立而不执行ans不会被错误更新随后l r 1使外层条件判假退出。两种写法殊途同归都保证了数组末端的 0 能被安全跳过。while (r n nums[r] 1) r;循环停止时有两种可能——r越界或者nums[r] 0。无论哪种[l, r)区间内的元素全部为 1段长度为r - l。注意区间是左闭右开的因此更新用的是r - l而非r - l 1。l r 1r位置要么是 0、要么越界前者不可能成为新连续段的起点下一次循环会被跳过后者说明数组已扫描完毕。因此直接从r 1继续是安全且最优的这正是把 O(n²) 压缩到 O(n) 的关键跳转。五、复杂度分析时间复杂度O(n)。l与r在整个扫描过程中只向右移动每个元素最多被访问常数次空间复杂度O(1)。只使用了常数个整型变量没有借助额外数组或哈希结构。在原文档中这两项复杂度结论直接标注在四段代码之后是本题作为「双指针模板题」最值得记忆的性质线性时间、常数空间。六、正确性论证与边界情况6.1 为什么跳过的候选起点不会影响答案这是本题唯一需要严谨论证的点。设当前左端点为lnums[l] 1其最远合法右边界为r。对于任意k \in [l 1, r]若把k作为左端点那么它能扩展出的连续 1 段必然被nums[r] 0或越界截断段长至多为r - k严格小于r - l。因此跳过这些起点只丢弃了「必不可能是全局最长」的方案答案的准确性不受影响。这正是双指针能在线性时间内完成扫描的理论依据。6.2 典型边界情况全 0 数组如[0,0,0]所有l都被跳过ans保持初始值 0正确全 1 数组如[1,1,1]l 0时r一路走到nans 3一次扫描完成单元素数组[0]得 0[1]得 1均由循环逻辑自然覆盖连续 1 段出现在数组末尾如[0,1,1]r越界时while正常停止长度按r - l计算依然正确无需特判。七、仓库延伸同构双指针题目的迁移「固定左端点找最远合法右端点、然后整体跳转」这一范式在刷穿 LeetCode 系列中反复出现仓库里有三题与 485 高度同构可作为巩固练习1446. 连续字符简单把「连续 1」换成「连续相同字符」同样是外层枚举段起点、内层用右指针找最远相同字符边界、按段长更新答案后整体跳转。代码骨架与 485 几乎一一对应是验证双指针模板掌握度的最佳练习。2760. 最长奇偶子数组简单题目改为找「先偶后奇交替、且元素不超过 threshold」的最长子数组。该题解完整论证了「跳过[i, j]之间作为左端点的方案只会漏掉必不可能是最长子数组的方案」并把朴素 O(n²) 优化到 O(n)——这正是 485 中「跳转」正确性论证的进阶版值得精读。1004. 最大连续1的个数 III中等允许把最多 K 个 0 翻转为 1求最长连续 1 段。题解给出了「动态规划TLE→ 前缀和 二分 → 双指针滑动窗口」的三步递进在 485 的扫描思路上引入窗口内 0 的计数约束左端点在窗口内 0 的个数超过 K 时才右移。从 485 到 1004 正好展示了双指针从「固定语义段扫描」到「带约束滑动窗口」的升级路径也是理解「根据数据范围选择算法」的绝佳案例。上述题目的题解链接均可在仓库的 双指针题单 与 滑动窗口题单 中定位到。八、小结LeetCode 485「最大连续 1 的个数」虽然难度为简单但它是双指针入门阶段的标杆题核心技巧用左右双指针把连续 1 段作为整体处理借助「中间起点必不更优」的论证实现整体跳转实现要点注意左闭右开区间的长度计算r - l以及数组末端 0 的越界安全处理各语言写法略有差异但语义一致复杂度特征O(n) 时间、O(1) 空间是面试中追求线性扫描时的标准答案迁移价值同一套「找最远合法右端点 整体跳转」的框架可直接迁移到连续字符、奇偶交替子数组、以及带翻转次数的滑动窗口变体中。掌握本题后建议按上述延伸题目依次练习并在提交时对照仓库中四语言代码检查边界处理即可完整吃透这一双指针基础范式。赞分享教程文档【免费下载链接】LogicStack-LeetCode公众号「宫水三叶的刷题日记」刷穿 LeetCode 系列文章源码项目地址https://gitcode.com/gh_mirrors/lo/LogicStack-LeetCode点击查看免费下载相关推荐LeetCode-Go 题解精讲485. Max Consecutive Ones 最大连续 1 的个数LeetCode Go 题解精讲485. Max Consecutive Ones 最大连续 1 的个数 导读 本文围绕 LeetCode 第 485 题「M示例工程连续数组LeetCode 525前缀和 哈希表求解最长 0/1 个数相等的子数组连续数组LeetCode 525前缀和 哈希表求解最长 0/1 个数相等的子数组 导读 本文围绕「刷穿 LeetCode」系列第 525 题的经典题解教程文档LeetCode 485 最大连续 1 的个数Max Consecutive Ones多语言解法全解析暴力、单次遍历与常见陷阱LeetCode 485 最大连续 1 的个数Max Consecutive Ones多语言解法全解析暴力、单次遍历与常见陷阱 导读 本文围绕 LeetC示例工程教程上一篇Meshbird与Docker集成容器化分布式网络的终极解决方案下一篇在 Kubernetes 上部署 GoNavi MCP Server基于 Kustomize 的最小集群清单实战指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考