1004. 最大连续1的个数 III
题目
给定一个二进制数组 nums
和一个整数 k
,假设最多可以翻转 k
个 0
,则返回执行操作后 数组中连续 1
的最大个数 。
示例 1:
输入:nums = [1,1,1,0,0,0,1,1,1,1,0], K = 2
输出:6
解释:[1,1,1,0,0,1,1,1,1,1,1]
粗体数字从 0 翻转到 1,最长的子数组长度为 6。
示例 2:
输入:nums = [0,0,1,1,0,0,1,1,1,0,1,1,0,0,0,1,1,1,1], K = 3
输出:10
解释:[0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1]
粗体数字从 0 翻转到 1,最长的子数组长度为 10。
提示:
1 <= nums.length <= 105
nums[i]
不是0
就是1
0 <= k <= nums.length
思路
为什么会想到用滑动窗口来解决呢?来自一位大佬的总结:
本题虽然可以使用滑动窗口的方法很快的解决,但是一些同学可能一开始很难去想到使用滑动窗口,那么如何看到一道滑动窗口题目就可以快速的想到使用滑动窗口去做,这里我给出了我的经验方法,希望能给大家带来帮助。
首先,既然我们要使用滑动窗口,肯定是希望算法的复杂度在O(N)的水平,所以当你看到所给的数组或字符串长度很大时(一般为10^5),就可以把滑动窗口作为一个候选算法了(也算是必要条件)。
补充:对于数据规模为105的数据,使用N2甚至更差的算法是一定会超时的!
接下来,滑动窗口都是要从一个数组中寻找符合某个条件的子串,即要寻找的结果一定是数组或字符串中连续的子区间,所以当你看到题目要寻找某个连续子区间时,也可以考虑使用滑动窗口了。
最后,题目除了给出要求寻找条件的数组外,还会给出相应的“条件”数据(或者说它的条件一定是由所给定的另一个数据的推出的)它可以是一个数字或者一个字符串等等。例如最小覆盖子串就是要从s
中寻找符合条件t
的子串(即子串能够涵盖t
所有字符的子串)以及本题就是从数组中寻找符合条件K
的子数组(即子数组中最多能有K
个0)。
如果你碰到一道题上述三个条件都满足,那么就不要犹豫,往滑动窗口的方向想就对了!
解法上和之前的没什么区别,只要能把问题转换成滑动窗口问题,这道题其实就已经解出来了
class Solution {
public int longestOnes(int[] nums, int k) {
// 问题被转化为:最多只有k个0的最长子数组长度
int maxLen = 0, count = 0, left = 0;
for (int right = 0; right < nums.length; right++) {
if (nums[right] == 0)
count++;
while (count > k) {
if (nums[left] == 0)
count--;
left++;
}
maxLen = Math.max(maxLen, right - left + 1);
}
return maxLen;
}
}