滑动窗口算法实战
1. 1004. 最大连续 1 的个数 III
题目描述

思路分析
这道题的核心是:找一个最长的子数组,其中最多包含 k 个 0。
经典的 滑动窗口 问题。
为什么用滑动窗口?
- 我们需要连续区间 → 滑动窗口天然适合
- 窗口内维护「0 的个数 ≤ k」这个约束
- 窗口扩张:右指针右移,遇到 0 就计数
- 窗口收缩:当 0 的个数超过 k,左指针右移直到满足条件
算法流程
1. 初始化:left = 0, zeroCount = 0, maxLen = 0
2. 遍历数组,right 指针右移:
- 如果 nums[right] == 0,zeroCount++
- 当 zeroCount > k 时,收缩左边界:
- 如果 nums[left] == 0,zeroCount--
- left++
- 更新 maxLen = max(maxLen, right - left + 1)
3. 返回 maxLen

代码实现
class Solution {
public:
int longestOnes(vector<int>& nums, int k) {
int zero = 0;
int ret = 0;
for (int left = 0, right = 0; right < nums.size(); right++) {
if (nums[right] == 0) zero++;
while (zero > k) {
if (nums[left++] == 0) zero--;
}
ret = max(ret, right - left + 1);
}
return ret;
}
};
2. 1658. 将 x 减到 0 的最小操作数
题目描述

给定一个整数数组 nums 和整数 x。每次操作可以从数组最左端或最右端移除一个元素,使 x 减去该元素的值。返回将 x 恰好减到 0 的最小操作数,无法实现则返回 -1。
示例:
输入:nums = [1,1,4,2,3], x = 5
输出:2
解释:移除最右端的 3,再移除最右端的 2,x = 5 - 3 - 2 = 0
思路分析
逆向思维 + 滑动窗口
从两端取数 → 等价于找一个中间连续子数组,其和为 total - x。
- 设数组总和为
sum - 问题转化为:找最长的子数组,使其和为
sum - x - 最小操作数 =
n - 最长子数组长度
为什么?
- 两端取走的元素和 =
x - 剩下中间的元素和 =
sum - x - 操作数最少 → 中间剩余最长
算法流程
1. 计算 target = sum(nums) - x
2. 如果 target < 0,返回 -1(总和都不够减)
3. 滑动窗口找和为 target 的最长子数组
4. 返回 n - maxLen(若 maxLen 有效)

代码实现
class Solution {
public:
int minOperations(vector<int>& nums, int x) {
int sum = 0;
int cmp = 0;
int ret = -1;
for (auto e : nums) {
sum += e;
}
int target = sum - x;
if (target < 0) return -1;
for (int left = 0, right = 0; right < nums.size(); right++) {
cmp += nums[right];
while (cmp > target) {
cmp -= nums[left++];
}
if (cmp == target) {
ret = max(ret, right - left + 1);
}
}
if (ret == -1) return ret;
else return nums.size() - ret;
}
};


