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

【LeetCode】最大连续1的个数 III

文章目录

  • 前言
  • 题目描述
  • 算法原理
  • 代码实现


前言

本文探讨了LeetCode题目1004(最大连续1的个数III)的解法。题目要求在二进制数组中翻转最多k个0后,找到连续1的最大长度。暴力解法通过两层循环枚举所有情况,但时间复杂度较高导致超时。优化解法采用滑动窗口技术,通过动态调整窗口左右边界,确保窗口内0的个数不超过k,从而高效计算最大连续1的长度。代码实现中,右指针遍历数组,左指针在0超标时移动收缩窗口,并实时更新最大长度。


题目链接:1004. 最大连续1的个数 III

题目描述

给定一个二进制数组 nums 和一个整数 k,假设最多可以翻转 k0 ,则返回执行操作后 数组中连续 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 <= 10^5
nums[i] 不是 0 就是 1
0 <= k <= nums.length

算法原理

题目给了我们一个二进制数组 nums 和一个整数 k,并且题目中说最多可以翻转 k0,它这个描述有点抽象,我们看下面的示例就好理解了,其实就是把 0 变成 1,注意题目那里说的是最多可以翻转 k0,然后让我们返回执行操作后数组中连续 1 的最大个数 。

题目的意思很好理解,但问题是我们要怎么写代码?这道题乍一看很简单,但翻转 k0 这个条件好像还不好处理,因为翻转的过程中可能和后面的 1 连起来,如示例 2,这种情况还比较复杂,直接下手不好处理。

这里我们可以转变一下思路,题目的要求我们还可以理解为:在一个二进制数组 nums 中,找出数组中连续 1 的最大个数,在这些 1 里面可以包含最多 k0,想通了这一点之后,下面我们看看这道题具体要怎么解决?

解法一:暴力解法
直接枚举所有可能得情况,先定义两个指针,从头开始遍历数组,遍历的过程中我们可以定义一个计数器 zero 来记录一下两个指针区间内的 0 的个数,当区间内 0 的个数大于 k 时,即找到一个符合条件的长度之后,我们再从第二个数开始,两层 for 循环就可以搞定。

代码如下:

class Solution 
{
public:int longestOnes(vector<int>& nums, int k) {int left = 0, right = 0, n = nums.size(), len = 0;for (int i = 0; i < n; i++){int size = 0, zero = 0;for (int j = i; j < n; j++){if (nums[j] == 1){size++;}else if (nums[j] == 0 && zero < k){zero++;size++;}else{break;}}len = len < size ? size : len;}return len;}
};

这种暴力枚举的解法比较容易想,代码也比较好写,但是会超时!

在这里插入图片描述
解法二:

这里我们还是以示例 1 为例来模拟一下暴力枚举的过程,然后尝试进行优化,如下图所示:

在这里插入图片描述

当我们第一次循环走到两个指针区间内 0 的个数大于 k 时,暴力解法我们是让 L 走到第二个元素的位置,然后 RL 的位置开始进行下一次循环,如下图所示:

在这里插入图片描述

到这里我们就发现问题了,第二次循环 L 虽然指向第二个元素了, 但 R 最终还是会走到与原来相同的位置,而且这一次循环肯定要比上一次循环得到的长度小。

这种情况下,R 最终还是会再次走到原先那个 0 的位置,所以 R 是完全可以不回退的,我们反而要让 L 继续向后走,直到两个指针区间内 0 的个数重新小于等于 k 为止

在这里插入图片描述
分析到这里,我们大致的思路就出来了,由于两个指针都是往后走,所以我们可以用 “滑动窗口” 来做这道题!

这个分析过程还是比较容易的,但能不能写出来就要考验我们的代码能力了,我刚开始做这道题的时候,想到了要用滑动窗口来做,但是写的代码却怎么都不通过,后面还是看了别人写的代码之后才过了的

这里主要还是要想清楚我们模拟滑动窗口的过程,即进窗口、判断、出窗口以及滑动过程中的更新结果这几步【要注意更新结果这一步在什么时候更新具体要看题,不一定就是在最后】。

代码实现

首先定义两个指针,然后就是不断地进窗口、判断、出窗口以及更新结果

class Solution 
{
public:int longestOnes(vector<int>& nums, int k) {int left = 0, right = 0, n = nums.size(), len = 0, zero = 0;while (right < n){if (nums[right] == 0){zero++;}while (zero > k){if (nums[left++] == 0){zero--;}}len = max(len, right - left + 1);right++;}return len;}
};

进窗口时如果是 1 就直接进,如果是 0 则计数器 zero + 1,进了一个元素之后我们就判断一下计数器 zero 是否大于 k,只要大于,就循环的出窗口,直到计数器 zero 重新小于 k截止,出完窗口我们就更新一下结果,直到右指针出数组循环就停止。


完!

http://www.dtcms.com/a/564719.html

相关文章:

  • Java 中 组合 (Composition)、接口 (Interface) 和 委托 (Delegation) 这三个概念的区别
  • 日本IT面试:与国内有何不同?一篇解析分享
  • 13-MySQL用户管理
  • 泰安放心的企业建站公司母婴网站源码 带采集
  • 做手机旅游网站徐州市制作网站的公司
  • 关于数控滑台
  • 数学中“必要条件”和“充分条件”大白话理解
  • 实验十一 三维观察实验
  • 【AI编码】VS Code - continue - github copolit
  • UVa 12298 Super Poker II
  • SQL视图:虚拟表的完整指南
  • 经纪柜台系统---拥有1.4.9号香港牌照的优选
  • 遵义网站建设天津做网站好的公司有哪些
  • 网站建设 响应式手机app制作网站
  • Elasticsearch 的 Routing 策略详解
  • GIT命令常用方法
  • Python计算题类相关实战
  • 常用es sql
  • 网站系统管理员烟台专业网站推广
  • 理论及算法_时间抽取论文
  • React中useContext的基本使用和原理解析
  • 重庆网站建设公司是什么意思可信赖的做网站
  • 【js逆向案例四】小红书
  • Next.js路由系统
  • 6、webgl 基本概念 + 四边形纹理
  • 【weblogic】XML反序列化漏洞
  • 20-控制流多次异步
  • Python Seaborn详解:让数据可视化更简单、更美观的利器
  • 基于c 的网站开发河北邢台路桥建设公司网站
  • VivaCut 4.4.0 | 专业的视频剪辑编辑制作工具,有非常多的特效,可替代剪映