【优选算法】 - 11.滑动窗口:最大连续1的个数③

引言

在今天的文章中,我们将聚焦于一个与数组处理相关的算法问题——最大连续1的个数(允许翻转K个0)。这个问题要求我们在一个二进制数组(即只包含0和1的数组)中,通过翻转最多k个0为1,来找出最长的连续1子数组的长度。为了高效地解决这个问题,我们将采用滑动窗口这一强大的技术。
leetcode-最大连续1的个数

问题描述

给定一个二进制数组 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。

解题思路

问题转化:找出最长的子数组,0的个数不超过k个。

思路1:暴力法(超时)
遍历所有可能的子数组,并检查每个子数组中0的个数。如果0的个数不超过k,则更新最大长度。然而,这种方法的时间复杂度为O(n^3),在数组较大时会超时。

思路2:滑动窗口,如下图所示

  1. 初始化:设置两个指针left和right作为窗口的左右边界,初始时都指向数组的开始位置。同时,设置变量zero来记录窗口中0的个数,初始值为0。变量len用于记录最长的连续1子数组的长度,初始值为0。
  2. 进窗口(移动右边界):通过循环,将右边界right向右移动,并检查当前元素是否为0。如果是,则zero加1。
  3. 判断,出窗口(调整窗口大小):在每次移动右边界后,检查zero是否大于k。如果是,说明窗口中0的个数超过了允许的范围,需要移动左边界left来缩小窗口,直到zero小于或等于k。在移动左边界的过程中,如果左边界指向的元素是0,则zero减1。
  4. 更新结果:在每次移动右边界或左边界后,计算当前窗口的长度(即right - left + 1),并将其与Len比较,更新len为较大值。
  5. 循环结束:当右边界right遍历完整个数组后,循环结束,此时len中存储的就是最长的连续1子数组的长度。
  6. 返回结果:返回len作为最终结果。
    在这里插入图片描述

代码实现

以下是使用暴力法,C++实现的代码示例: (超时)

class Solution {
public:
    int longestOnes(vector<int>& nums, int k) {
        int left , right ,zero = 0,  len=0;
        int n = nums.size();
        for(left = 0; left < n; left++) {
            zero = 0;
        
            for(right = left; right < n ; right++){
                if(nums[right]==0) zero++;
                if(zero > k) break;
                len = max(len , right - left + 1);
            }
        }
        return len;
    }
};

以下是使用滑动窗口,C++实现的代码示例:

class Solution {
public:
    int longestOnes(vector<int>& nums, int k) {
        int left , right ,zero = 0, len=0;
        int n = nums.size();
        for(left = 0,right = 0; right < n; right++){
            if(nums[right]==0)
                zero++;
            while(zero>k){
                if(nums[left]==0)
                    zero--;
                left++;
            }
            len = max(len , right-left+1);
        }
        return len;
    }
};

这段代码通过滑动窗口技术高效地解决了问题,时间复杂度为O(n),其中n是数组的长度。

  • 9
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值