其他系列文章导航
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
。思路与算法:
重点:题意转换。把「 返回最长的且只包含 1 的非空子数组的长度 」转换为 「 返回最长带有一个 0 的非空子数组的长度 - 1 」。
经过上面的题意转换,我们可知本题是求最大连续子区间,可以使用滑动窗口方法。滑动窗口的限制条件是:窗口内最多有 1 个 0。
可以使用我多次分享的滑动窗口模板解决,模板在代码之后。
再次申明模板很重要,可以解决一些列的题目。
首先定义四个变量:
代码思路:
滑动窗口算法是一种常用的算法,用于解决数组或列表中的子数组问题。下面是一个滑动窗口算法的解题模板:
下面是一个具体的例子,使用滑动窗口算法求解数组中连续子数组的最大和:
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即可。
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& 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 = 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
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
}