滑动窗口算法实战:两道经典题目解析
滑动窗口是处理数组子区间问题的利器,尤其适用于寻找满足特定条件的最长或最短子数组。今天我们来深入探讨两个典型应用:最大连续 1 的个数 III 和 将 x 减到 0 的最小操作数。
1. 最大连续 1 的个数 III
题目描述: 给定一个二进制数组和一个整数 k,你可以将最多 k 个 0 翻转为 1。求翻转后数组中最长连续 1 的子数组的长度。
解题思路: 不要纠结于'翻转'这个动作本身。换个角度想,这其实是在原数组中寻找一段最长的连续区间,使得这段区间内包含的 0 的个数不超过 k 个。一旦找到了这样的区间,我们就能通过翻转其中的 0 来得到全 1 序列。既然是找连续区间,滑动窗口再合适不过了。
算法流程:
维护一个滑动窗口 [left, right],用变量 zero 记录当前窗口内 0 的数量。
- 右指针
right向右移动,每遇到一个 0,zero加一。 - 如果
zero超过了 k,说明窗口不合法,需要收缩左边界。左指针left右移,直到窗口内的 0 减少到 k 个为止。 - 每次调整完窗口后,更新最大长度
ret。
代码实现:
class Solution {
public:
int longestOnes(vector<int>& nums, int k) {
int ret = 0;
// left 和 right 作为窗口边界,zero 统计窗口内 0 的个数
for (int left = 0, right = 0, zero = 0; right < nums.size(); right++) {
// 元素进入窗口
if (nums[right] == 0) zero++;
// 如果 0 的个数超标,收缩左边界
while (zero > k) {
if (nums[left++] == 0) zero--;
}
// 更新结果:当前窗口长度
ret = max(ret, right - left + 1);
}
return ret;
}
};


