【每日一题】LeetCode 1004.最大连续1的个数 III(数组、双指针、滑动窗口)
题目描述
给定一个二进制数组 nums
和一个整数 k
,如果可以翻转最多 k
个 0,则返回数组中连续 1 的最大个数。
思路分析
这个问题可以通过滑动窗口的方法来解决。滑动窗口的左右边界分别表示数组中一段连续的子数组的开始和结束位置。我们的目标是找到最大的子数组,使得这个子数组中 0 的数量不超过 k
,并且这个子数组的长度最大。
- 初始化两个指针
left
和right
来表示窗口的边界,以及一个变量count
来记录窗口中 0 的数量。 - 遍历数组,当
right
指针指向的位置是 0 时,增加count
。 - 如果
count
大于k
,说明当前窗口内 0 的数量超过了允许的范围,需要移动left
指针直到count
不超过k
。 - 在每一步,都更新最大长度
max
,即right - left + 1
。 - 重复步骤 2-4,直到
right
指针遍历完整个数组。
输入示例
示例 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 0翻转到 1,最长的子数组长度为 10。
提示:
1 <= nums.length <= 10^5
nums[i]
不是 0 就是 10 <= k <= nums.length
代码实现
class Solution {
public int longestOnes(int[] nums, int k) {
// 如果数组长度等于k,说明所有0都可以被翻转,最大长度就是数组长度
if(nums.length == k) {
return k;
}
int left = 0; // 滑动窗口的左边界
int right = 0; // 滑动窗口的右边界
int max = 0; // 记录最大长度
int count = 0; // 记录窗口内0的数量
// 遍历数组
while (right < nums.length) {
// 如果当前位置是0,增加count
if (nums[right] == 0) {
count++;
}
// 当count超过k时,移动left指针直到count不超过k
while (count > k) {
if (nums[left] == 0) {
count--;
}
left++;
}
// 更新最大长度
max = Math.max(max, right - left + 1);
// 移动right指针
right++;
}
return max;
}
}