当前位置: 首页 > news >正文

【算法滑动窗口】最大的连续1的个数III

在这里插入图片描述

最大的连续1的个数III

    • 滑动窗口使用的条件:
    • 题目描述:
    • 解题思路:
    • AI的解题思路
      • 最终代码实现
      • 关键逻辑注释

我们先来说明一下什么时候会去使用到滑动窗口来解决问题:
当题目满足以下3个条件时,用滑动窗口:

滑动窗口使用的条件:

1:题目求的是「连续的子数组/子串」
1. 比如:连续的一段数字、连续的字符串片段
2. ❌ 如果题目允许不连续(如子序列),不能用滑动窗口

2:题目要求的是「最大长度」或「最小长度」

比如:

  1. 最长无重复子串(最大长度)
  2. 最短的满足和≥target的子数组(最小长度)

3:窗口的扩张和收缩有明确的规则

  1. 扩张(右指针右移):探索新元素,更新状态(如字符计数、和值)
  2. 收缩(左指针右移):当窗口不满足条件时调整(如重复字符、和超过target)

题目描述:

1004.最大的连续1的个数III

给定一个二进制数组 nums 和一个整数 k,假设最多可以翻转 k 个 0 ,则返回执行操作后 数组中连续 1 的最大个数 。

示例 1:

输入:nums = [1,1,1,0,0,0,1,1,1,1,0], K = 2
输出:6
解释:[1,1,1,0,0,1,1,1,1,1,1]
粗体数字从 0 翻转到 1,最长的子数组长度为 6。
示例 2:

输入:nums = [0,0,1,1,0,0,1,1,1,0,1,1,0,0,0,1,1,1,1], K = 3
输出:10
解释:[0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1]
粗体数字从 0 翻转到 1,最长的子数组长度为 10。

提示:

1 <= nums.length <= 105
nums[i] 不是 0 就是 1
0 <= k <= nums.length

解题思路:

我们可以将这一道转化为:
找出最长的连续1的子数组,在这个子数组中0的个数不超过k个:

接下来我使用一个特殊的总结归纳方法来解除这道题目,在下面的一问一答之间,穿插好题目的讲解

第一步:用自己的话,描述一下眼前的这个问题,它是一个怎么样的问题?

这个问题的目的是为了在这个只有0和1的数组中,找出最大的连续1的子数组,同时在这个子数组中的0不超过k个,此时刚好都满足了滑动窗口的条件。

第二步:这个问题有哪些特征,能让我们去判断,它属于这一类的问题?

  1. 第一个特征:题目要求的是一个连续的子数组
  2. 第二个特征:题目要求的是最大的连续的为1的子数组
  3. 第三个特征:题目要求在这个子数组中0的个数不超过k个

题目的要求就需要使用到同向双指针去动态调整子数组:

为什么要使用到同向双指针呢?

为了找到最大的连续1的子数组,需要让right指针去不停地向右扩张

为了保证在这个子数组中0的个数不超过k个:

所以当right指针不停地向右扩张,导致子数组中0的个数超过了k个的时候,那就需要让left指针将多于的0去除掉,这就是同向双指针动态调整子数组(窗口)的过程,也就称之为滑动窗口。

第三步:想要解决这类问题,切入点啥,即第一步我们要从哪里开始?

先去判定这道题目是否符合滑动窗口的要求,发现这道题完全符合,那就开始使用for循环来通过同向双指针去动态调整子数组了

第四步:解决这个问题的流程是怎么样的?这里说的流程是指,这道题可以分成12345…步,只要按照12345这个顺序做下去,我们就能解决这个问题。

  1. 判定题目要求是否是连续最长/最短子数组,是否需要动态调整子数组
  2. 是的话,定义int变量ret为最终结果(最大的连续1的个数),同时使用for循环,一个int的zero变量来计算子数组中0的个数,让right指针向右扩张,遇到0,那就将zero加一。
  3. 如果在扩张的过程中,需要不停地判断0的个数zero是不是大于了k
  4. 如果判定0的个数大于了k,那就去判断left指针位置处的值是不是0,如果是0,那么就让zero减一,同时让left向右移动一位,如果下一个left位置依旧是0,那就继续让zero减一,同时left继续向右移动一位,知道zero不超过k为止
  5. 经过上面的循环之后,此时left和right之间的子数组就是满足条件的子数组(连续为1,0的个数不超过k个)
  6. 此时就更新最终结果ret就是(right-left+1):更新结果

第五步:在流程的12345步中,每一步的目标是什么(就是要求到些什么)?每一步需要用到哪些知识

  1. 判定是不是滑动窗口的题目,是不是求连续的子数组
  2. 在for循环中,通过ret变量来计算出最终的结果,通过zero变量来计算子数组中的0的个数,通过zero判定是否要进入窗口和出窗口,当right向右移动,tight的位置出现了0,那就zero+1
  3. 在for循环中right不停地向右走时,zero+1,要使用while循环去不停地判断zero是不是超过了k,当zero超过了k,此时说明子数组中0超过了k个,就需要减少0的个数,就是让left也开始向右移动,当left的位置也是0的时候,就zero减一,同时left++一次,就代表子数组减少了一个0,此时也就是需要不停地判断zero是不是还是大于k的,是,那么就继续上述操作,不是,那就跳出这个判断的while循环(出窗口),然后去进行结果的更新

第六步:要思考在运用这些知识和技巧的时候,有些需要注意的地方。

  1. 这个题目是求的是最长的连续子数组
  2. 使用的是同向双指针的方式
  3. 使用while循环来不停地判断是否要进行出窗口的操作
  4. 在出窗口之后,满足了条件之后层,才要去跟新结果

第七步:要解决这个问题,最终的目标是啥?也就是说,我最终要求出的是啥?

最终的目标是为了去求出一个长度,这个数组中连续为1的最大的的子数组的长度

第八步:重新对上面的第一步至第七步,进行回顾和揣摩(包括问题类型,特征,切入点,解决过程,1234567…步,每步需要用的哪些知识方法)

(2)AI+8步归纳结合
在模仿完题目后,先自己用8步归纳法对错题进行归纳,然后让deepseek,按照8步归纳法的原则,对题目进行总结归纳,你再把自己总结归纳出的东西,跟AI对比,看看有哪些地方可以改进。

在这里插入图片描述


上面是我自己根据这八个步骤去总结归纳的解题流程,下面是根据DeepSeek归纳总结出来的流程:

AI的解题思路


第一步:问题描述:用自己的话,描述一下眼前的这个问题,它是一个怎么样的问题
问题本质
在二进制数组中,允许最多翻转k个0为1的情况下,找到最长的连续1的子数组的长度。


第二步:问题特征:这个问题有哪些特征,能让我们去判断,它属于这一类的问题?

  1. 连续子数组:结果必须是连续的元素
  2. 最值问题:要求最大长度
  3. 动态调整:窗口内0的数量受k限制,需动态调整窗口大小
  4. 滑动窗口适用:符合“连续子数组 + 最值”的经典特征

第三步:解题切入点:想要解决这类问题,切入点啥,即第一步我们要从哪里开始?

  1. 判断是否属于滑动窗口问题(连续子数组 + 最值)
  2. 定义窗口状态变量zero(记录窗口内0的数量)
  3. 用双指针动态维护窗口的合法性(zero ≤ k

第四步:解题流程:解决这个问题的流程是怎么样的?这里说的流程是指,这道题可以分成12345…步,只要按照12345这个顺序做下去,我们就能解决这个问题。

  1. 初始化

    • left = 0(左指针)
    • zero = 0(窗口内0的数量)
    • ret = 0(最终结果)
  2. 右指针扩张

    • right从0开始遍历数组
    • 遇到nums[right] == 0时,zero++
  3. 左指针收缩

    • zero > k时,移动left直到zero ≤ k
      • nums[left] == 0,则zero--
      • left++
  4. 更新结果

    • 计算当前窗口长度right - left + 1
    • 更新ret = max(ret, 当前长度)

第五步:每步目标与知识点:在流程的12345步中,每一步的目标是什么(就是要求到些什么)?每一步需要用到哪些知识

步骤目标关键知识点
初始化定义初始状态变量初始化
右指针扩张探索新元素遍历数组
左指针收缩保证窗口合法性条件判断与指针移动
更新结果记录最大值数学比较操作

第六步:注意事项:要思考在运用这些知识和技巧的时候,有些需要注意的地方。

  1. 更新时机:在左指针收缩更新结果(因为是求最大窗口)
  2. 边界处理:当k >= 总0数时,直接返回数组长度
  3. 效率优化:每个元素最多被访问两次,时间复杂度O(n)

第七步:最终目标:要解决这个问题,最终的目标是啥?也就是说,我最终要求出的是啥?
求出允许翻转k个0时,数组中连续1的最长子数组长度


第八步:整体回顾

  1. 问题类型:滑动窗口(最大窗口问题)
  2. 核心特征:连续子数组、动态调整、最值
  3. 解决流程
    • 右指针扩张探索
    • 左指针收缩保证合法性
    • 收缩后更新结果
  4. 关键点:窗口状态的维护(zero计数器)

最终代码实现

class Solution {public int longestOnes(int[] nums, int k) {int n = nums.length;int zero = 0;      // 窗口内0的数量int ret = 0;       // 最终结果int left = 0;      // 左指针for (int right = 0; right < n; right++) {if (nums[right] == 0) zero++;  // 右指针扩张,更新0的数量// 当0的数量超过k时,收缩左指针while (zero > k) {              if (nums[left] == 0) zero--; // 移出的是0,则减少计数left++;                      }// 更新最大长度(收缩后窗口一定合法)ret = Math.max(ret, right - left + 1); }return ret;}
}

关键逻辑注释

  1. 右指针扩张:探索新元素,统计0的数量。
  2. 左指针收缩:当0的数量超过k时,逐步移出窗口左侧元素,直到合法。
  3. 更新结果:在每次窗口调整后,计算当前合法窗口的长度并更新最大值。

在这里插入图片描述
在这里插入图片描述

相关文章:

  • 一种快速计算OTA PSRR的方法(Ⅱ)
  • ARM架构详解:定义、应用及特点
  • Qt结构体运算符重载指南
  • 爱胜品ICSP YPS-1133DN Plus黑白激光打印机报“自动进纸盒进纸失败”处理方法之一
  • patch命令在代码管理中的应用
  • 【论文速递】2025年09周 (Robotics/Embodied AI/LLM)
  • RAG技术完全指南(三):LlamaIndex架构解析与私有知识库搭建
  • 【五一培训】Day 2
  • 【quantity】5 derive_more库 2.0 版介绍
  • 藏文情感分析器入门学习实践
  • 正态分布全景解析:理论、推导与应用
  • aws(学习笔记第四十课) image-content-search
  • 【Java IO流】字节输入流FileInputStream、字节输出流FileOutputStream
  • Servlet 解决了什么问题?
  • 数字智慧方案6190丨智慧应急综合平台解决方案(49页PPT)(文末有下载方式)
  • 数字智慧方案5856丨智慧环保综合解决方案(50页PPT)(文末有下载方式)
  • C# 多态性详解:从静态到动态的编程艺术
  • 类与对象(中)
  • SpringBoot基础(原理、项目搭建、yaml)
  • 【C++】红黑树迭代版
  • 严正交涉!我驻日使馆:如日方采取新的挑衅举动,中方必坚决反制
  • 青海大学常务副校长(正厅级)任延明已任省卫健委党组书记
  • 抗战回望15︱《五月国耻纪念专号》:“不堪回首”
  • 2024年境内酒店住宿行业指标同比下滑:酒店行业传统增长模式面临挑战
  • 遍体鳞伤就是击不倒,这是国米老男孩最后的倔强
  • 讲武谈兵|朝鲜“崔贤”号驱逐舰下水,朝版“宙斯盾”战力如何?