题目描述

LeetCode——最大连续1的个数 III(滑动窗口)_算法

解题思路

本题的核心思路是滑动窗口,而滑动窗口的实现需要借助双指针,这是解决本题的核心思路。

  1. 定义滑动窗口的左右边界。
let l = 0;
let r = 0;
  1. 定义滑动窗口中连续1的个数(包含K个零)
let max = 0;
  1. 定义滑动窗口中零的个数。
let zeros = 0;
  1. 核心循环体
  • 进入循环的条件是右边界越界
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;
};

执行结果

LeetCode——最大连续1的个数 III(滑动窗口)_滑动窗口_02

题目反思

  • 学会使用滑动窗口的方式求解子区间、子数组问题。
  • 学会使用更新的方式获取最大值。