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

【LeetCode 每日一题】1493. 删掉一个元素以后全为 1 的最长子数组——(解法一)预处理

Problem: 1493. 删掉一个元素以后全为 1 的最长子数组

文章目录

  • 整体思路
  • 完整代码
  • 时空复杂度
    • 时间复杂度:O(N)
    • 空间复杂度:O(Z) 或 O(N)

整体思路

这段代码旨在解决一个特定的数组问题:“删除一个元素后全为 1 的最长子数组”。问题要求在给定的二进制数组 nums 中,必须删除一个元素,然后找出结果数组中只包含 1 的最长子数组的长度。

该算法采用了一种非常巧妙的 预处理 策略,而不是传统的滑动窗口。它首先识别出所有障碍物(即 0),然后计算移除每个障碍物后可能形成的最长连续 1 区间的长度。

其核心逻辑步骤如下:

  1. 识别并记录所有 0 的位置

    • 算法的核心是 List<Integer> zeroLoc,它被用来存储数组中所有 0 元素的索引。
    • 哨兵(Sentinel)技巧:在开始扫描之前,代码巧妙地向 zeroLoc 中添加了两个“哨兵”值:-1n(数组长度)。
      • -1 代表数组开始之前的一个虚拟的 0。
      • n 代表数组结束之后的一个虚拟的 0。
    • 目的:这两个哨兵极大地简化了边界情况的处理。例如,当我们考虑删除第一个实际的 0 时,可以利用 -1 作为它“左边”的 0 的位置;同样,删除最后一个实际的 0 时,可以利用 n 作为它“右边”的 0 的位置。这避免了在主循环中写大量的 if/else 来处理首尾的特殊情况。
  2. 处理特殊情况(全为 1)

    • 在记录完所有 0 的位置后,代码检查 zeroLoc 的大小。如果 size == 2,这意味着列表中只有两个哨兵 -1n,说明原始数组中没有任何 0
    • 根据题意,我们必须删除一个元素。因此,从一个全为 1 的数组中删除任意一个 1,得到的最长子数组长度就是 n - 1。代码正确地处理了这种情况。
  3. 计算移除每个 0 后的最长长度

    • 算法的主体是一个 for 循环,它遍历 zeroLoc 列表中所有实际的 0 的索引(即排除首尾的哨兵)。
    • 对于列表中的第 i 个实际的 0(其索引在 zeroLoc 中是 i),如果我们将它删除,那么它原来左边的连续 1 和右边的连续 1 就会合并成一个更长的连续 1 子数组。
    • 这个合并后的子数组的边界,恰好是由这个 0 的前一个 0后一个 0 的位置所限定的。
    • 长度计算
      • 前一个 0 的索引是 zeroLoc.get(i - 1)
      • 后一个 0 的索引是 zeroLoc.get(i + 1)
      • 这两个 0 之间的总元素个数是 zeroLoc.get(i + 1) - zeroLoc.get(i - 1) - 1
      • 这个区间内包含了一个我们想要删除的 0,所以纯 1 的个数就是 (zeroLoc.get(i + 1) - zeroLoc.get(i - 1) - 1) - 1,即 zeroLoc.get(i + 1) - zeroLoc.get(i - 1) - 2
    • 算法在循环中不断计算这个值,并用 ans 变量来记录遇到的最大值。
  4. 返回结果

    • 遍历结束后,ans 中存储的就是最终的答案。

完整代码

import java.util.ArrayList;
import java.util.List;class Solution {/*** 删除一个元素后,返回数组中全为 1 的最长子数组的长度。* @param nums 二进制数组* @return 最长子数组的长度*/public int longestSubarray(int[] nums) {int n = nums.length;// ans: 用于存储最终结果,即找到的最长子数组的长度int ans = 0;// zeroLoc: 用于存储所有 0 元素的索引List<Integer> zeroLoc = new ArrayList<>();// 关键技巧:添加哨兵(sentinel)值// -1 代表数组开始前的一个虚拟的 0zeroLoc.add(-1); // 步骤 1: 遍历数组,记录所有实际 0 的位置for (int i = 0; i < n; i++) {if (nums[i] == 0) {zeroLoc.add(i);}}// n 代表数组结束后一个虚拟的 0zeroLoc.add(n); // 获取包含哨兵在内的 0 的总数int size = zeroLoc.size();// 步骤 2: 处理特殊情况// 如果 size 为 2,说明列表中只有哨兵[-1, n],即原数组中没有 0。// 题目要求必须删除一个元素,所以从全 1 的数组中删除一个,长度为 n-1。if (size == 2) {return n - 1;} // 步骤 3: 遍历每一个实际的 0,计算删除它之后能形成的最长 1 子数组// 循环从 i=1 到 size-2,正好遍历所有实际的 0,跳过哨兵for (int i = 1; i < size - 1; i++) {// zeroLoc.get(i) 是当前要“删除”的 0 的索引// zeroLoc.get(i - 1) 是它前一个 0 的索引(可能是哨兵 -1)// zeroLoc.get(i + 1) 是它后一个 0 的索引(可能是哨兵 n)// 这两个 0 之间的区间长度,减去两个 0 本身,就是合并后的 1 的数量。int currentLength = zeroLoc.get(i + 1) - zeroLoc.get(i - 1) - 2;ans = Math.max(ans, currentLength);}return ans;}
}

时空复杂度

时间复杂度:O(N)

  1. 查找 0 的位置:第一个 for 循环遍历整个 nums 数组一次,以找到所有 0 的索引。这个过程的时间复杂度是 O(N)
  2. 计算最大长度:第二个 for 循环遍历 zeroLoc 列表。设 nums 数组中 0 的数量为 Z,则 zeroLoc 的大小为 Z+2,这个循环执行 Z 次。
  3. 综合分析
    • 总的时间复杂度为 O(N) (扫描数组) + O(Z) (扫描0列表)。
    • 由于 0 的数量 Z 不可能超过数组的总长度 N(即 Z <= N),所以 O(N) + O(Z) 可以简化为 O(N)

空间复杂度:O(Z) 或 O(N)

  1. 主要存储开销:算法使用了一个 ArrayList 类型的 zeroLoc 来存储所有 0 的索引。
  2. 空间大小
    • 列表 zeroLoc 的大小等于数组中 0 的数量 Z 加上两个哨兵,即 Z+2
    • 在最坏的情况下,nums 数组中可能全是 0,此时 Z = NzeroLoc 的大小将与输入规模 N 成线性关系。
  3. 综合分析
    • 算法所需的额外空间主要由 zeroLoc 列表决定。因此,其空间复杂度为 O(Z),其中 Z 是数组中 0 的个数。
    • 在最坏情况下,空间复杂度为 O(N)

文章转载自:

http://PeT2EKMZ.bszmy.cn
http://TeWjh5v5.bszmy.cn
http://OJWFCGMs.bszmy.cn
http://0pqvOOQU.bszmy.cn
http://OVtEqSnN.bszmy.cn
http://K9guPJP9.bszmy.cn
http://gsczORKi.bszmy.cn
http://nJXUTNBF.bszmy.cn
http://OBgNm4J3.bszmy.cn
http://mrBaRFCS.bszmy.cn
http://z0VzrLDs.bszmy.cn
http://khCO7NVJ.bszmy.cn
http://Up6zST7b.bszmy.cn
http://7Q5icXGm.bszmy.cn
http://qKBzSkKQ.bszmy.cn
http://aFR5tP17.bszmy.cn
http://vEGZo7IW.bszmy.cn
http://ngCiflma.bszmy.cn
http://yu2tcJoc.bszmy.cn
http://fWd6bNUK.bszmy.cn
http://01CCjFed.bszmy.cn
http://4Jd4l0pk.bszmy.cn
http://yxNa7IhZ.bszmy.cn
http://gzqipLaA.bszmy.cn
http://yww8UsUw.bszmy.cn
http://UYPNXNIm.bszmy.cn
http://hODz7Zjy.bszmy.cn
http://d5gZcObl.bszmy.cn
http://c2DitIt4.bszmy.cn
http://BzBkKLqT.bszmy.cn
http://www.dtcms.com/a/376848.html

相关文章:

  • Java代理模式详解
  • 【论文阅读】MEDDINOV3:如何调整视觉基础模型用于医学图像分割?
  • 超声波探伤的所用到的频段?
  • 关于ping不通,如何排查?
  • const allImages = { ...leftCategoryImages, ...rightCategoryImages }; 是是什么用法
  • 论文阅读:arxiv 2023 Large Language Models are Not Stable Recommender Systems
  • Transformer系列 | Pytorch复现Transformer
  • 神经网络常见层速查表
  • 算法练习——55.跳跃游戏
  • linux驱动开发
  • 今日分享 二分算法及多语言实现
  • 【代码随想录算法训练营——Day8】字符串——344.反转字符串、541.反转字符串II、卡码网:54.替换数字
  • 软件项目验收中第三方检测服务总流程
  • Python采集1688拍立淘按图搜索,json数据返回
  • 【卷积神经网络详解与实例】4——感受野
  • 多模态学习双核引擎:对齐建立连接,融合释放价值
  • unity开发类似个人网站空间
  • 【不背八股】10.Redis知识点汇总
  • MySQL 整型数据类型:选对数字类型,让存储效率翻倍
  • OpenCV的图像金字塔
  • PMP考试学习计划与知识大纲
  • 自然语言处理开源框架全面分析
  • antd v5 support React is 16 ~ 18. see https://u.ant.design/v5-for-19 for...
  • 【硬件-笔试面试题-82】硬件/电子工程师,笔试面试题(知识点:讲讲单片机的内部晶振与外部晶振)
  • 【计算机网络 | 第12篇】网络应用原理
  • 【竞赛系列】机器学习实操项目05——客户信用评估模型进阶流程(含XGBoost、LightGBM、CatBoost 高级模型对比与参数优化)
  • 机器学习的本质:从跑模型到真正解决问题
  • LeakCanary最新稳定版
  • 个人博客系统-测试报告
  • 生活中的各种造型 参考多图