这是我参与8月更文挑战的第12天,活动详情查看:8月更文挑战
题目描述
解题思路
本题的核心思路是滑动窗口,而滑动窗口的实现需要借助双指针,这是解决本题的核心思路。
- 定义滑动窗口的左右边界。
let l = 0; let r = 0; 复制代码
- 定义滑动窗口中连续1的个数(包含K个零)
let max = 0; 复制代码
- 定义滑动窗口中零的个数。
let zeros = 0; 复制代码
- 核心循环体
- 进入循环的条件是右边界越界
while (r < nums.length) 复制代码
- 判断滑动窗口中零的个数和K的关系
只有两种关系,要么滑动窗口中零的个数小于等于K,要么大于K,如果小于K,说明窗口右边界还未满足条件,还需要继续扩充右边界,此时让r++,但是在右边界扩充的时候,我们要看当前右指针指向的元素是0还是1,如果是1则直接向右扩充即可,但是如果是1,则需要更新0的个数之后,继续扩充,如果零的个数大于K,则需要移动左边界,在移动左边界的时候,依然要考虑上述因素。
if (zeros <= k) { if (nums[r] === 1) { r++; } else { r++; zeros++; } } if (zeros > k) { if (nums[l] === 0) { zeros--; l++; } else { l++; } } 复制代码
- 更新最大值(因为r总是先移动后判断,所以用右边界-左边界就可以和最大值进行比较更新)
if (r - l > max) { max = r - l; } 复制代码
AC代码
// 核心思路: 滑动窗口 + 更新最大值 var longestOnes = function (nums, k) { // 定义滑动窗口的左右边界 let l = 0; let r = 0; // 定义滑动窗口中连续1(包含K个零)的最大值 let max = 0; // 定义滑动窗口中0的个数 let zeros = 0; // 进入循环的条件是:滑动窗口的右边界没有越界 while (r < nums.length) { if (zeros <= k) { if (nums[r] === 1) { r++; } else { r++; zeros++; } } if (zeros > k) { if (nums[l] === 0) { zeros--; l++; } else { l++; } } if (r - l > max) { max = r - l; } } return max; }; 复制代码
执行结果
题目反思
- 学会使用滑动窗口的方式求解子区间、子数组问题。
- 学会使用更新的方式获取最大值。