【数据结构和算法】删掉一个元素以后全为 1 的最长子数组

简介: 这是力扣的 1493 题,难度为中等,解题方案有很多种,本文讲解我认为最奇妙的一种。又又又是一道滑动窗口的典型例题,可以帮助我们巩固滑动窗口算法。这道题很活灵活现,需要加深对题意的变相理解。给你一个二进制数组nums,你需要从中删掉一个元素。请你在删掉元素的结果数组中,返回最长的且只包含 1 的非空子数组的长度。如果不存在这样的子数组,请返回 0 。

 其他系列文章导航

Java基础合集

数据结构与算法合集

设计模式合集

多线程合集

分布式合集

ES合集


文章目录

其他系列文章导航

文章目录

前言

一、题目描述

二、题解

2.1 方法一:滑动窗口

2.2 滑动窗口解题模板

三、代码

3.1 方法一:滑动窗口

四、复杂度分析

4.1 方法一:滑动窗口


前言

这是力扣的 1493 题,难度为中等,解题方案有很多种,本文讲解我认为最奇妙的一种。

又又又是一道滑动窗口的典型例题,可以帮助我们巩固滑动窗口算法。

这道题很活灵活现,需要加深对题意的变相理解。


一、题目描述

给你一个二进制数组 nums ,你需要从中删掉一个元素。

请你在删掉元素的结果数组中,返回最长的且只包含 1 的非空子数组的长度。

如果不存在这样的子数组,请返回 0 。

提示 1:

输入:nums = [1,1,0,1]

输出:3

解释:删掉位置 2 的数后,[1,1,1] 包含 3 个 1 。

示例 2:

输入:nums = [0,1,1,1,0,1,1,0,1]

输出:5

解释:删掉位置 4 的数字后,[0,1,1,1,1,1,0,1] 的最长全 1 子数组为 [1,1,1,1,1] 。

示例 3:

输入:nums = [1,1,1]

输出:2

解释:你必须要删除一个元素。


提示:

    • 1 <= nums.length <= 105
    • nums[i] 要么是 0 要么是 1

    二、题解

    2.1 方法一:滑动窗口

    思路与算法:

    重点:题意转换。把「 返回最长的且只包含 1 的非空子数组的长度 」转换为 「 返回最长带有一个 0 的非空子数组的长度 - 1 」。

    经过上面的题意转换,我们可知本题是求最大连续子区间,可以使用滑动窗口方法。滑动窗口的限制条件是:窗口内最多有 1 个 0。

    可以使用我多次分享的滑动窗口模板解决,模板在代码之后。

    再次申明模板很重要,可以解决一些列的题目。

    首先定义四个变量:

      1. 左指针
      2. 右指针
      3. 最长的子串长度
      4. 0 的数量

      image.gif编辑

      代码思路:

        1. 使用 left 和 right 两个指针,分别指向滑动窗口的左右边界。
        2. right 主动右移:right 指针每次移动一步。当 nums[right] 为 0,说明滑动窗口内增加了一个 0;
        3. left 被动右移:判断此时窗口内 0 的个数,如果超过了 K,则 left 指针被迫右移,直至窗口内的 0 的个数小于等于 K 为止。
        4. 滑动窗口长度的最大值就是所求。记得最后要减去 1 ,因为子数组里还多了一个 0 。

        image.gif编辑

        2.2 滑动窗口解题模板

        滑动窗口算法是一种常用的算法,用于解决数组或列表中的子数组问题。下面是一个滑动窗口算法的解题模板:

          1. 定义窗口大小:首先需要确定滑动窗口的大小,即每次滑动时包含的元素个数。
          2. 初始化窗口:将窗口的起始位置设置为0,窗口大小设置为n,其中n为数组或列表的长度。
          3. 计算窗口中的元素和:使用一个变量sum来记录当前窗口中的元素和,初始值为0。
          4. 移动窗口:从左到右依次遍历数组或列表,每次将当前元素加入窗口中,并更新sum的值。
          5. 判断是否满足条件:在移动窗口的过程中,不断判断当前窗口中的元素和是否满足题目要求。如果满足条件,则返回当前窗口中的元素和。
          6. 移动窗口:如果当前窗口中的元素和不满足题目要求,则将窗口向右移动一位,并更新sum的值。
          7. 重复步骤4-6,直到遍历完整个数组或列表。

          下面是一个具体的例子,使用滑动窗口算法求解数组中连续子数组的最大和:

          def maxSubArray(nums):  
              if not nums:  
                  return 0  
              max_sum = current_sum = nums[0]  
              for i in range(1, len(nums)):  
                  current_sum = max(nums[i], current_sum + nums[i])  
                  max_sum = max(max_sum, current_sum)  
              return max_sum

          image.gif

          在这个例子中,我们使用一个变量max_sum来记录当前最大子数组的和,一个变量current_sum来记录当前窗口中的元素和。在遍历数组的过程中,不断更新current_sum的值,并判断是否满足题目要求。如果满足条件,则更新max_sum的值。最后返回max_sum即可。


          三、代码

          3.1 方法一:滑动窗口

          Java版本:

          class Solution {
              public int longestSubarray(int[] nums) {
              int left = 0, right = 0, zero = 0, longestSubarray = 0, n = nums.length;
                  while (right < n) {
                      if (nums[right] == 0) zero++;
                      if (zero > 1) {
                          left++;
                          if (nums[left - 1] == 0) zero--;
                      }
                      if (zero == 1 || right == n - 1) {
                          longestSubarray = Math.max(longestSubarray, right - left + 1);
                      }
                      right++;
                  }
                  return longestSubarray - 1;
              }
          }

          image.gif

          C++版本:

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

          image.gif

          Python版本:

          class Solution:
              def longestSubarray(self, nums: List[int]) -> int:
                  left = 0
                  right = 0
                  zero = 0
                  longestSubarray = 0
                  n = len(nums)
                  while right < n:
                      if nums[right] == 0:
                          zero += 1
                      if zero > 1:
                          left += 1
                          if nums[left - 1] == 0:
                              zero -= 1
                      if zero == 1 or right == n - 1:
                          longestSubarray = max(longestSubarray, right - left + 1)
                      right += 1
                  return longestSubarray - 1

          image.gif

          Go版本:

          func longestSubarray(nums []int) int {
              left := 0
              right := 0
              zero := 0
              longestSubarray := 0
              n := len(nums)
              for right < n {
                  if nums[right] == 0 {
                      zero++
                  }
                  if zero > 1 {
                      left++
                      if nums[left-1] == 0 {
                          zero--
                      }
                  }
                  if zero == 1 || right == n-1 {
                      longestSubarray = max(longestSubarray, right-left+1)
                  }
                  right++
              }
              return longestSubarray - 1
          }
          func max(a, b int) int {
              if a > b {
                  return a
              }
              return b
          }

          image.gif


          四、复杂度分析

          4.1 方法一:滑动窗口

            • 时间复杂度:O(N),因为每个元素只遍历了一次。
            • 空间复杂度:O(1),因为使用了常数个空间。


            目录
            相关文章
            |
            17天前
            |
            存储 机器学习/深度学习 算法
            C 408—《数据结构》算法题基础篇—链表(下)
            408考研——《数据结构》算法题基础篇之链表(下)。
            80 29
            |
            17天前
            |
            存储 算法 C语言
            C 408—《数据结构》算法题基础篇—链表(上)
            408考研——《数据结构》算法题基础篇之链表(上)。
            75 25
            |
            17天前
            |
            存储 人工智能 算法
            C 408—《数据结构》算法题基础篇—数组(通俗易懂)
            408考研——《数据结构》算法题基础篇之数组。(408算法题的入门)
            60 23
            |
            1月前
            |
            存储 算法 测试技术
            【C++数据结构——树】二叉树的遍历算法(头歌教学实验平台习题) 【合集】
            本任务旨在实现二叉树的遍历,包括先序、中序、后序和层次遍历。首先介绍了二叉树的基本概念与结构定义,并通过C++代码示例展示了如何定义二叉树节点及构建二叉树。接着详细讲解了四种遍历方法的递归实现逻辑,以及层次遍历中队列的应用。最后提供了测试用例和预期输出,确保代码正确性。通过这些内容,帮助读者理解并掌握二叉树遍历的核心思想与实现技巧。
            52 2
            |
            2月前
            |
            存储 运维 监控
            探索局域网电脑监控软件:Python算法与数据结构的巧妙结合
            在数字化时代,局域网电脑监控软件成为企业管理和IT运维的重要工具,确保数据安全和网络稳定。本文探讨其背后的关键技术——Python中的算法与数据结构,如字典用于高效存储设备信息,以及数据收集、异常检测和聚合算法提升监控效率。通过Python代码示例,展示了如何实现基本监控功能,帮助读者理解其工作原理并激发技术兴趣。
            70 20
            |
            5天前
            |
            算法 数据安全/隐私保护 计算机视觉
            基于FPGA的图像双线性插值算法verilog实现,包括tb测试文件和MATLAB辅助验证
            本项目展示了256×256图像通过双线性插值放大至512×512的效果,无水印展示。使用Matlab 2022a和Vivado 2019.2开发,提供完整代码及详细中文注释、操作视频。核心程序实现图像缩放,并在Matlab中验证效果。双线性插值算法通过FPGA高效实现图像缩放,确保质量。
            |
            1月前
            |
            算法 数据安全/隐私保护 计算机视觉
            基于Retinex算法的图像去雾matlab仿真
            本项目展示了基于Retinex算法的图像去雾技术。完整程序运行效果无水印,使用Matlab2022a开发。核心代码包含详细中文注释和操作步骤视频。Retinex理论由Edwin Land提出,旨在分离图像的光照和反射分量,增强图像对比度、颜色和细节,尤其在雾天条件下表现优异,有效解决图像去雾问题。
            |
            1天前
            |
            算法
            基于遗传优化算法的风力机位置布局matlab仿真
            本项目基于遗传优化算法(GA)进行风力机位置布局的MATLAB仿真,旨在最大化风场发电效率。使用MATLAB2022A版本运行,核心代码通过迭代选择、交叉、变异等操作优化风力机布局。输出包括优化收敛曲线和最佳布局图。遗传算法模拟生物进化机制,通过初始化、选择、交叉、变异和精英保留等步骤,在复杂约束条件下找到最优布局方案,提升风场整体能源产出效率。
            |
            1月前
            |
            算法 数据可视化 安全
            基于DWA优化算法的机器人路径规划matlab仿真
            本项目基于DWA优化算法实现机器人路径规划的MATLAB仿真,适用于动态环境下的自主导航。使用MATLAB2022A版本运行,展示路径规划和预测结果。核心代码通过散点图和轨迹图可视化路径点及预测路径。DWA算法通过定义速度空间、采样候选动作并评估其优劣(目标方向性、障碍物距离、速度一致性),实时调整机器人运动参数,确保安全避障并接近目标。
            149 68
            |
            1天前
            |
            算法 安全 机器人
            基于包围盒的机械臂防碰撞算法matlab仿真
            基于包围盒的机械臂防碰撞算法通过构建包围盒来近似表示机械臂及其环境中各实体的空间占用,检测包围盒是否相交以预判并规避潜在碰撞风险。该算法适用于复杂结构对象,通过细分目标对象并逐级检测,确保操作安全。系统采用MATLAB2022a开发,仿真结果显示其有效性。此技术广泛应用于机器人运动规划与控制领域,确保机器人在复杂环境中的安全作业。

            热门文章

            最新文章