题目描述

✅ 485. 最大连续 1 的个数

image-20260928224130363

题意分析

数组中只有 $0$ 和 $1$,求最长连续一段 $1$ 的长度。连续段必须占据相邻位置,遇到 $0$ 就被切断,不能通过跳过、删除或翻转 $0$ 把两段合并。

解法:线性扫描

核心思路

[!blue]

扫描过程中,只有当前末尾这段连续的 $1$ 还可能向后延长;已经被 $0$ 截断的段不会参与后续新段,只需保留它们贡献过的最大长度。因此用两个变量就能记录全部必要信息:cur 是以当前元素结尾的连续 $1$ 的长度,best 是已扫描前缀中出现过的最大长度。

  • 当前元素为 $1$:它可以接在上一位置结尾的连续段后面,所以执行 cur++;再用新的 cur 更新 best。若上一项是 $0$,此前的 cur 为 $0$,这一步就自然开始长度为 $1$ 的新段。
  • 当前元素为 $0$:不存在以它结尾的全 $1$ 片段,令 cur = 0。历史最长段仍然有效,best 不变。

初始还没有读取任何元素,两个长度都为 $0$。每处理一项,上述更新都保持两个变量的含义;遍历结束后,best 已经覆盖所有可能的连续段,就是答案。

每次遇到 $1$ 都立即更新最大值,因此最后一段即使没有被 $0$ 结尾,也不会漏算。全零数组的答案保持为 $0$,全一数组则会不断延长到整个数组长度,无需额外分支。

解题步骤

  • 初始化当前长度与最大长度为零。
  • 遇到一,先延长再更新最大值。
  • 遇到零,当前长度归零。
  • 返回全局最大值。

代码实现

class Solution {
    // 遇到 1 则计数加一,遇到 0 则重置为 0。
    public int findMaxConsecutiveOnes(int[] nums) {
        int cur = 0;
        int best = 0;

        for (int num : nums) {
            if (num == 1) {
                cur++;
                // 延长后立即刷新,末尾没有零也不会漏记最长段
                best = Math.max(best, cur);
            } else {
                // 零切断当前连续段,历史最大值不清空
                cur = 0;
            }
        }

        return best;
    }
}
func findMaxConsecutiveOnes(nums []int) int {
    // 遇到 1 则计数加一,遇到 0 则重置为 0。
    cur := 0
    best := 0

    for _, v := range nums {
        if v == 1 {
            cur++
            // 延长后立即刷新,末尾没有零也不会漏记最长段
            if cur > best {
                best = cur
            }
        } else {
            // 零切断当前连续段,历史最大值不清空
            cur = 0
        }
    }

    return best
}

复杂度分析

  • 时间复杂度:$O(n)$,只扫描一次。
  • 空间复杂度:$O(1)$,两个计数变量。

关键点总结

[!green]

  • 当前末端长度与全局最长长度是两个状态。
  • 遇到零后不能继承前一段长度。

易错点总结

[!yellow]

  • 遇到零只把 cur 减一,会让已经断开的前一段残留到后面的计数中;必须归零。
  • 只在遇到零时更新答案,会漏掉全一或末尾最长段。
  • 返回 cur 会丢掉前面更长、但已经结束的段。

相似题目

题目 难度 关联与区别
1004. 最大连续1的个数 III 中等 允许翻转k个0后,连续1统计扩展成零数不超过k的滑动窗口。
1493. 删掉一个元素以后全为 1 的最长子数组 中等 原题必须删除一个位置,本题不做修改,只统计已有连续1段。
转载与许可
作者
链接 https://hgnulb.github.io/blog/2022/39421249
许可 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!