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:
输入: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 翻转到 1,最长的子数组长度为 10。
提示:
1 <= nums.length <= 105
nums[i]
不是0
就是1
0 <= k <= nums.length
思路
- 首先定义两个指针,右指针先将可翻转数拉满,找到作为初始的滑动窗口。
- 然后没遇到下一个需要翻转的,先统计窗口长度,再将左指针一直后移到窗口内第一个待翻转点后,然后窗口继续后移,直到窗口到达下一个待翻转点或到达数组末尾,最后输出最长窗口长度即可。
- 最后补充考虑指针的情况将细节完善即可:
- 左右指针在同一个位置;
- 右指针在后;
- k是否等于0。
- 两个指针指向的地方是否都是0.
- 将以上几个情况都组合搭配实现窗口移动逻辑。
代码实现
class Solution {
public:
int longestOnes(vector<int>& nums, int k) {
int left = 0, right = 0, max_length = 0;
while(1) {
if(right==nums.size()) {
max_length = max(max_length, right-left);
break;
}
if(k>0){
if(nums[right]==0) k--;
right++;
}
else if(k==0){
if(left==right) {
if(nums[right]==0) {
left++;
right++;
}
else right++;
}
else if(left<right) {
if(nums[right]==0) {
if(nums[left]==0) {
left++;
right++;
}
else {
max_length = max(max_length, right-left);
left++;
}
}
else right++;
}
}
}
return max_length;
}
};
复杂度分析
- 时间复杂度:双指针移动,右指针遍历一次完整数组,时间复杂度为O(n)。
- 空间复杂度:O(1)。
官方题解
- 官方题解还介绍了个二分查找法,感觉不容易想到,而且效率也不如滑动窗口,就不看了。