目录
[1. 题目解析](#1. 题目解析)
[2. 算法原理 + 编写代码](#2. 算法原理 + 编写代码)
[解法一:暴力枚举 + zero计数器](#解法一:暴力枚举 + zero计数器)
1. 题目解析
题目:1004. 最大连续1的个数 III
OJ链接:1004. 最大连续1的个数 III - 力扣(LeetCode)
给定一个二进制数组 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. 算法原理 + 编写代码
转化思路 :找出最长的子数组,其中 0的个数不超过 k个。
解法一:暴力枚举 + zero计数器
通过双重循环枚举所有子数组,统计每个子数组中 0的个数,超过 k则停止扩展,记录最大长度。
java
class Solution {
public int longestOnes(int[] nums, int k) {
int n = nums.length;
int maxLen = 0;
// 遍历所有可能的子数组起点i
for (int i = 0; i < n; i++) {
int zeroCount = 0; // 统计当前子数组中0的个数
// 遍历所有可能的子数组终点j(j >= i)
for (int j = i; j < n; j++) {
if (nums[j] == 0) {
zeroCount++;
}
// 如果0的个数超过k,就不需要继续扩展j了(因为子数组是连续的,再往后j,0的个数只会更多
if (zeroCount > k) {
break;
}
// 更新最大长度
maxLen = Math.max(maxLen, j - i + 1);
}
}
return maxLen;
}
}
解法二:滑动窗口
通过维护一个滑动窗口,保证窗口内 0的个数不超过 k,逐步扩大窗口并更新最大长度。
步骤:
-
初始化
left = 0,right = 0,zero = 0。 -
右指针
right遍历数组,进窗口 :若nums[right]为0,zero计数 +1。 -
判断 :若
zero > k,则需要移动左指针left缩小窗口,出窗口 :若nums[left]为0,zero计数 -1,左指针右移。 -
更新结果 :每次窗口合法时,更新最大长度
ret = Math.max(ret, right - left + 1)。
java
class Solution {
public int longestOnes(int[] nums, int k) {
int ret = 0;
for (int left = 0, right = 0, zero = 0; right < nums.length; right++) {
if (nums[right] == 0) zero++; // 进窗口
while (zero > k) { // 判断
if (nums[left++] == 0) zero--; // 出窗口
}
ret = Math.max(ret, right - left + 1); // 更新结果
}
return ret;
}
}