https://blog.csdn.net/2601_95366422/article/details/158570599
上节课链接
一.题目
1004. 最大连续1的个数 III – 力扣(LeetCode)

二.思路
对于这道题,题目给定一个二进制数组,允许将最多 k 个 0 翻转为 1,要求找出最长的连续 1 的子数组长度。由于子数组必须是连续的,所以很自然地会想到用滑动窗口来处理。
滑动窗口的核心是维护一个区间,通过移动左右指针来调整窗口大小,从而在遍历过程中找到满足条件的最优解。本题中,我们允许翻转 0,但翻转次数有限,所以窗口内的 0 的个数不能超过 k。换句话说,只要窗口内 0 的数量 ≤ k,我们就可以通过翻转使窗口内全部变成 1,这个窗口就是有效的。
因此,我们可以将问题转化为:寻找一个最长的连续子数组,使得其中 0 的个数不超过 k。这完全符合滑动窗口的应用场景。
在具体实现思路上,我们通过右指针不断向右扩展窗口(进窗口),每遇到一个 0 就计数加 1。当窗口内 0 的个数超过 k 时,就需要移动左指针(出窗口)来减少 0 的个数,直到满足条件。在每次调整后,我们记录当前窗口的长度,并更新最大值。这样遍历完整个数组后,就能得到最长子数组的长度。
三.代码演示
class Solution {
public:
int longestOnes(vector<int>& nums, int k)
{
int n = nums.size();
int zero = 0;
int len = 0;
for (int left = 0, right = 0; right < n;right++)
{
//进窗口
if(nums[right] == 0)
zero++;
//判断条件
while(zero > k)
{
//出窗口
if(nums[left] == 0)
zero–;
left++;
}
//更新条件
len = max(len,right – left + 1);
}
return len;
}
};
四.代码讲解
第一步:初始化变量 获取数组长度 n,定义变量 zero 用于记录当前窗口内 0 的个数,初始值为 0。定义变量 len 用于存储 最长连续 1 的长度(即满足条件的最大窗口长度),初始值为 0。同时设置左指针 left 和右指针 right 均从 0 开始。
第二步:遍历数组,移动右指针 使用 for 循环,让右指针 right 从 0 到 n-1 依次遍历数组。每次循环开始时,右指针指向当前要加入窗口的元素。
第三步:进窗口 当右指针指向的元素 nums[right] 为 0 时,将 zero 计数加 1,表示窗口内 0 的个数增加。这一步相当于将当前元素纳入窗口。
第四步:判断并出窗口 检查当前窗口内 0 的个数是否超过允许的最大值 k。如果 zero > k,说明窗口内 0 太多,需要 收缩左边界 以移除一些 0:
-
先检查左指针指向的元素 nums[left] 是否为 0,如果是,则将 zero 减 1。
-
然后将左指针 left 向右移动一位(left++),即 将左侧元素移出窗口。 重复这个过程,直到 zero <= k,保证窗口始终满足条件。
第五步:更新结果 当窗口满足条件(即 zero <= k)后,计算当前窗口的长度 right – left + 1,并用它更新最大长度 len,即 len = max(len, 当前窗口长度)。这一步记录下 当前最长有效窗口。




