问题解析
题目要求:给定一个二进制数组 nums 和一个整数 k,你可以将最多 k 个 0 翻转为 1。请返回在执行任意次数的翻转操作后,数组中最长的连续 1子数组的长度 。
核心思路 :将问题转化为寻找一个最长的子数组,使得该子数组内 0 的个数不超过 k 个 。这可以通过滑动窗口(同向双指针) 算法高效解决。
算法流程 :
1.初始化左指针 left = 0,窗口内 0 的计数器 zeroCount = 0,以及结果 maxLen = 0。
- 右指针
right从0开始遍历数组:
* 进窗口 :如果 nums[right] == 0,则 zeroCount++ 。
* 判断与收缩 :当 zeroCount > k 时,说明当前窗口内 0 的数量超过了可翻转的上限。此时需要收缩左边界,即 left 右移。如果移出窗口的元素是 0,则 zeroCount-- 。
* 更新结果 :在每次右指针移动并完成可能的窗口收缩后,当前窗口 [left, right] 一定满足条件( 0 的数量 ≤ k)。此时更新最大长度 maxLen = max(maxLen, right - left + 1) 。
复杂度分析:
- 时间复杂度:O(n),每个元素最多被访问两次(右指针一次,左指针一次)。
- 空间复杂度:O(1),仅使用了常数个额外变量。
C++ 代码实现:
cpp
class Solution {
public:
int longestOnes(vector<int>& nums, int k) {
int left = 0; // 窗口左边界 int zeroCount = 0; // 窗口内0的个数
int maxLen = 0; // 记录最大长度
// 右指针遍历整个数组
for (int right = 0; right < nums.size(); ++right) {
// 1. 右指针元素进窗口
if (nums[right] == 0) {
zeroCount++;
}
// 2. 判断:如果窗口内0的数量超过k,需要收缩左边界
while (zeroCount > k) {
if (nums[left] == 0) {
zeroCount--;
}
left++; // 左指针右移,窗口收缩
}
// 3. 更新最大长度 (此时窗口[left, right]一定满足条件)
maxLen = max(maxLen, right - left + 1);
}
return maxLen;
}
};