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

其他系列文章导航

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 的数量

代码思路:

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

 

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

在这个例子中,我们使用一个变量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;}
}

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;}
};

Python版本:

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

Go版本: 

func longestSubarray(nums []int) int {left := 0right := 0zero := 0longestSubarray := 0n := 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
}

四、复杂度分析

4.1 方法一:滑动窗口

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/298549.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【每日一题】美丽塔 II

Tag 【单调栈】【数组】【2023-12-21】 题目来源 2866. 美丽塔 II 题目解读 题目意思相对明确&#xff0c;所谓的美丽塔数组就是山状数组&#xff0c;即有一个高度为 maxHeight[i] 的山峰&#xff0c;山峰两侧的高度要小于 maxHeight[i] 并且小于各自的允许高度。需要找出满…

台达A2-M伺服

地址: P3.00 从站地址0x01~0x7F【1~127】 P3.01 通讯速度UZYX【0403】 X:0【4800】1【9600】2【19200】3【38400】4【57600】5【115200】Z:0【125Kbit/s】1【250】2【500】3【750】4【1Mbit/s】 P3.02 通讯格式6【8N2】7【8E1】8【8O1】 P3.03 1通讯错误刹停…

每日一题——LeetCode141.环形链表

个人主页&#xff1a;白日依山璟 专栏&#xff1a;Java|数据结构与算法|每日一题 文章目录 1. 题目描述示例1&#xff1a;示例2&#xff1a;示例3&#xff1a;提示: 2. 思路3. 代码 1. 题目描述 给你一个链表的头节点 head &#xff0c;判断链表中是否有环。 如果链表中有某…

synchronized详解

synchronized详解 基本使用源码解析常见面试题好书推荐 基本使用 Java中的synchronized关键字用于在多线程环境下确保数据同步。它可以用来修饰方法和代码块 当一个线程访问一个对象的synchronized方法或代码块时&#xff0c;其他线程将无法访问该对象的其他synchronized方法…

QT 构建项目报错Could not initialize class org.codehaus.groovy.vmplugin.v7.Java7

问题 Getting NoClassDefFoundError: Could not initialize class org.codehaus.groovy.vmplugin.v7.Java7获取 NoClassDefFoundError&#xff1a;无法初始化类 org.codehaus.groovy.vmplugin.v7.Java7 解决方法一 java版本 过高 将java版本降低&#xff0c;例如从java17降…

「Verilog学习笔记」并串转换

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点&#xff0c;刷题网站用的是牛客网 串并转换操作是非常灵活的操作&#xff0c;核心思想就是移位。串转并就是把1位的输入放到N位reg的最低位&#xff0c;然后N位reg左移一位&#xff0c;在把1位输入放到左移后…

「模问题」AI原生小游戏强势来袭!

WAVE SUMMIT 深度学习开发者大会2023 举办在即&#xff0c;为了让大家更好地体验文心大模型的各项能力&#xff0c;掌握Prompt的使用技巧&#xff0c;我们带来一个惊喜的消息&#xff1a;全新AI原生小游戏——「模问题」火热上线啦&#xff01; 「模问题」是基于文心大模型的能…

磁钢的取向和充磁方向

充磁是磁钢生产中的必备工序&#xff0c;如果磁铁不充磁&#xff0c;就不具备磁性&#xff0c;也就丧失了作为永磁材料的基本功能。磁钢作为一个立体的工件&#xff0c;形状和尺寸各异&#xff0c;如何给磁钢充磁&#xff1f;不同方向的充磁效果一样吗&#xff1f;今天我们就来…

智能仓储管理系统设计与实现

智能仓储管理系统设计与实现 第一章 绪论 1.1 设计背景 物联网&#xff08;英文&#xff1a;Internet of Things&#xff0c;缩写&#xff1a;IoT&#xff09;是万物相连的互联网&#xff0c;即把所有物品通过信息传感设备与互联网连接起来&#xff0c;以实现智能化识别、定位、…

C++ 比 C语言增加的新特性 3 之 命名空间namespace

1. 命名空间 1.1 命名空间 又称为“名字空间”&#xff0c;在内存&#xff08;全局&#xff09;中取一块区域并对其进行命名 实际例子&#xff1a; 同一个班级&#xff0c;两个同姓的人&#xff0c;例如&#xff1a;张三和张三&#xff0c;其中一个张三座位是在讲台右边&am…

Tg5032skn:高稳定性105℃高温

TG5032SKN是一款频率范围10MHz ~ 54MHz,具有高稳定的TCXO晶振&#xff0c;可与CMOS或裁剪正弦输出。外部尺寸5.0 3.2 1.45mm&#xff0c;超小型,质地轻。该系列晶振的额定工作范围-40℃~&#xfe62;105C内可高稳定性工作&#xff0c;使得信号频率的误差很小。。TG5032SKN与其…