news 2026/10/19 13:06:20

LeetCode 485. 最大连续 1 的个数(简单):双指针线性扫描求最长连续 1 段

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LeetCode 485. 最大连续 1 的个数(简单):双指针线性扫描求最长连续 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。

因此扫描流程可以设计为:

  1. 令l从数组头开始扫描;
  2. 若nums[l] == 0,说明它不可能是连续 1 段的开头,l直接右移跳过;
  3. 若nums[l] == 1,令r = l,向右找到第一个不满足「r在界内且nums[r] == 1」的位置,此时[l, r)全为 1,长度r - l更新ans;
  4. 令l = r + 1,从该位置继续处理(r位置本身是 0 或越界,不可能作为新段的开头)。

这样每个位置最多被l和r各访问常数次,整个扫描是严格线性的 O(n)。

三、四种语言的完整实现

原文档为这道题提供了 Java、C++、Python、TypeScript 四种可直接提交的实现,以下代码完整保留原文档写法。

Java

class 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; } }

C++

class Solution { public: int findMaxConsecutiveOnes(vector<int>& 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; } };

Python

class 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 ans

TypeScript

function 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; };

四、代码细节解读:边界安全与跳转逻辑

这几段代码里有几处值得展开的细节,理解它们能避免在真实提交时踩坑:

  1. if (nums[l] == 0 && ++l >= 0) continue;(Java/TypeScript 版):由于l始终是非负整数,++l >= 0恒为真,所以这行的实际效果等价于「l先自增,然后continue回到循环条件判断」。当l恰好是最后一个元素且为 0 时,++l后l == n,外层for条件l < n直接判假退出,不会发生越界访问。

  2. if (nums[l] == 0 && ++l < n) continue;(C++ 版):写法略有差异,多带了一个界内判断。当nums[l] == 0且++l后仍小于n时继续循环;若++l后l == n(即最后一个元素是 0),则不continue,而是进入下面的逻辑——此时r = l且l == n,while (r < n && nums[r] == 1)因为r == n不成立而不执行,ans不会被错误更新,随后l = r + 1使外层条件判假退出。两种写法殊途同归,都保证了数组末端的 0 能被安全跳过。

  3. while (r < n && nums[r] == 1) r++;:循环停止时有两种可能——r越界,或者nums[r] == 0。无论哪种,[l, r)区间内的元素全部为 1,段长度为r - l。注意区间是左闭右开的,因此更新用的是r - l而非r - l + 1。

  4. l = r + 1:r位置要么是 0、要么越界,前者不可能成为新连续段的起点(下一次循环会被跳过),后者说明数组已扫描完毕。因此直接从r + 1继续是安全且最优的,这正是把 O(n²) 压缩到 O(n) 的关键跳转。

五、复杂度分析

  • 时间复杂度:O(n)。l与r在整个扫描过程中只向右移动,每个元素最多被访问常数次;
  • 空间复杂度:O(1)。只使用了常数个整型变量,没有借助额外数组或哈希结构。

在原文档中,这两项复杂度结论直接标注在四段代码之后,是本题作为「双指针模板题」最值得记忆的性质:线性时间、常数空间。

六、正确性论证与边界情况

6.1 为什么跳过的候选起点不会影响答案

这是本题唯一需要严谨论证的点。设当前左端点为l(nums[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一路走到n,ans = 3,一次扫描完成;
  • 单元素数组:[0]得 0,[1]得 1,均由循环逻辑自然覆盖;
  • 连续 1 段出现在数组末尾:如[0,1,1],r越界时while正常停止,长度按r - l计算依然正确,无需特判。

七、仓库延伸:同构双指针题目的迁移

「固定左端点找最远合法右端点、然后整体跳转」这一范式在刷穿 LeetCode 系列中反复出现,仓库里有三题与 485 高度同构,可作为巩固练习:

  1. 1446. 连续字符(简单):把「连续 1」换成「连续相同字符」,同样是外层枚举段起点、内层用右指针找最远相同字符边界、按段长更新答案后整体跳转。代码骨架与 485 几乎一一对应,是验证双指针模板掌握度的最佳练习。

  2. 2760. 最长奇偶子数组(简单):题目改为找「先偶后奇交替、且元素不超过 threshold」的最长子数组。该题解完整论证了「跳过[i, j]之间作为左端点的方案,只会漏掉必不可能是最长子数组的方案」,并把朴素 O(n²) 优化到 O(n)——这正是 485 中「跳转」正确性论证的进阶版,值得精读。

  3. 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
点击查看免费下载
上一篇:Meshbird与Docker集成:容器化分布式网络的终极解决方案
下一篇:在 Kubernetes 上部署 GoNavi MCP Server:基于 Kustomize 的最小集群清单实战指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/14 20:35:37

windows下mysql中binlog日志分析和数据恢复

1.首先查看是否开启了binlog show variables like %log_bin%;看到了是没有开启的。 2.开启binlog日志&#xff0c;并重启mysql服务 不能通过命令的方式去打开&#xff0c;因为会提示说这个参数是只读的。如下图&#xff1a;所以&#xff0c;打开mysql的配置文件&#xff0c;找到…

作者头像 李华
网站建设 2026/10/15 1:27:33

PCA9422+MK60DN512VLQ10低功耗电源管理方案设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/16 15:25:46

基于YOLOv5的直肠息肉检测:完整程序、数据集与RK3568量化部署实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/17 9:22:17

最大熵模型预测实战:从原理到栅格生成的避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/17 19:28:47

基于LSH的论文相似性快速比对技术实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华