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 <= 105nums[i]不是 0 就是 10 <= k <= nums.length
解法
方法一:滑动窗口
思考
枚举所有子数组并统计其中 \(0\) 的个数需要 \(O(n^2)\),而 \(n\le 10^5\),不可行。所求是「至多翻转 \(k\) 个 \(0\)」后最长的连续 \(1\),等价于最长且含 \(0\) 不超过 \(k\) 个的窗口。
窗口右端每前进一步,若零的个数超过 \(k\),则左端也必须前进以恢复可行性。题目只要最长长度,窗口只需单调变长,左端每次至多移动一格,不必缩到合法后再继续。
用 \(l\) 与 \(\textit{cnt}\) 维护当前窗口:右端扫过每个位置,超限则丢掉左端的一个位置。结束时 \(n-l\) 即为最大可行窗口长度。
我们可以遍历数组,用一个变量 \(\textit{cnt}\) 记录当前窗口中 0 的个数,当 \(\textit{cnt} > k\) 时,我们将窗口的左边界右移一位。
遍历结束后,窗口的长度即为最大连续 1 的个数。
注意,在上述过程中,我们不需要循环将窗口的左边界右移,而是直接将左边界右移一位,这是因为,题目求的是最大连续 1 的个数,因此,窗口的长度只会增加,不会减少,所以我们不需要循环右移左边界。
时间复杂度 \(O(n)\),其中 \(n\) 为数组的长度。空间复杂度 \(O(1)\)。
相似题目:
1 2 3 4 5 6 7 8 9 | |
1 2 3 4 5 6 7 8 9 10 11 12 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
1 2 3 4 5 6 7 8 9 10 11 | |
1 2 3 4 5 6 7 8 9 10 | |