看到leetcode上面一道关于滑动算法的题目。挺有意思,记录一下
1004. 最大连续1的个数 III
给定一个由若干 0 和 1 组成的数组 A,我们最多可以将 K 个值从 0 变成 1 。
返回仅包含 1 的最长(连续)子数组的长度。
示例 1:
输入:A = [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:
输入:A = [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。
思路:
- 标准的滑动窗口的题目,首先定义窗口左右侧变量(left, right),定义当前还剩余的机会数l,以及定义当前的最大长度m。
- 遍历数组, 判断right的值,如果为1则不消耗任何机会,窗口右侧向右移动。如果为0,要进一步判断当前的机会数,如果机会已经用完了,窗口左侧往右移动。若机会还没有用完,窗口右侧向右移动。
- 每次遍历的时候都需要更新一下当前最大长度,即max(m, right - left)
代码:
/**
* @param {number[]} A
* @param {number} K
* @return {number}
*/
var longestOnes = function(A, K) {
let left = 0, right = 0;
let l = K;
let m = 0; // 最大值
if (A.length <= K) {
return A.length
}
// 贪吃蛇算法,详情可看题解那个带佬的算法
while (right < A.length) {
if (A[right] === 0) {
// 下一个是0
if (l === 0) {
// 没有机会了
if (A[left] === 0) {
// 最左侧是0,排除了一个0,机会+1
l++
}
left++
} else {
// 机会还有剩余的
l--
right++
}
} else {
// 下一个不是0,不消耗机会
right++
}
m = Math.max(m, right - left)
}
return m
};