滑动窗口是处理连续子数组问题的高效技巧。今天通过两道经典题目,深入理解其基础应用及逆向思维转化。
题目一:最大连续 1 的个数 III
核心思路
这道题要求找到最长的子数组,其中最多包含 k 个 0。这是典型的滑动窗口场景。
为什么选滑动窗口?因为我们需要维护一个连续区间,且窗口内满足「0 的个数 ≤ k」这一约束。右指针负责扩张窗口,左指针负责在条件不满足时收缩。
具体操作
- 初始化左右指针和计数器。
- 右指针遍历数组,遇到 0 则计数增加。
- 一旦 0 的数量超过 k,移动左指针直到满足条件(移除多余的 0)。
- 每次合法后更新最大长度。
代码实现
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;
}
};
注意这里 ret 的更新时机,是在窗口收缩完成后,确保当前窗口始终合法。
题目二:将 x 减到 0 的最小操作数
核心思路
这道题看似要从两端取数,其实可以转化为中间子数组的问题。
如果从两端取走的元素和为 x,那么剩下的中间部分和就是 总和 - x。为了让操作数最少,等价于让剩下的中间子数组最长。
转化逻辑
- 计算数组总和
sum。


