每日一道leetcode(补充版)
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)。
官方题解
- 官方题解还介绍了个二分查找法,感觉不容易想到,而且效率也不如滑动窗口,就不看了。