滑动窗口(3)_最大连续1的数组个数III

个人主页:C++忠实粉丝
欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 C++忠实粉丝 原创

滑动窗口(3)_最大连续1的数组个数III

收录于专栏【经典算法练习
本专栏旨在分享学习算法的一点学习笔记,欢迎大家在评论区交流讨论💌

目录

1. 题目链接:

2. 题目描述 :

3. 解法 :

    解法一(暴力枚举) :

    算法思路 :

    具体步骤 :

    代码展示 :

    结果分析 :

对暴力算法的反思与优化  

    解法二(滑动窗口) :

    算法思路 :

    图解流程 :

    代码展示 :

    结果分析 :


1. 题目链接:

OJ链接: 最大连续1的个数III 

2. 题目描述 :

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

3. 解法 :

    解法一(暴力枚举) :

    算法思路 :

这道题将0转换成1的操作实现起来非常不方便,对于暴力算法来说,每次转换完后,下次一又得恢复原样,那我们可不可以不要转换,直接通过判断0的个数不超过k来找到最长子数组呢?

通过上面的分析,我们就可以把题目转换为 : 找出最长的子数组,0的个数不超过k个

那么我们就可以使用暴力枚举,在使用一个变量记录0的个数,找出数组中所有可能的子数组,然后用max取最大值,即题目所需要的最长的子数组.

    具体步骤 :

  1. i,j两层循环遍历整个数组
  2. 用tmp记录遍历时0的个数
  3. 当tmp > k时当前遍历完成
  4. i++,j = i进入下一轮遍历

    代码展示 :

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

 

    结果分析 :

这道题比上到题狠,这道题数组中数据的个数在10^5之内,我们暴力算法的时间复杂度为O(N^2),总的数据级别在10^10之上,计算机无法的1s内完成,所以判定超时!!!

对暴力算法的反思与优化  

当我们的暴力循环到这种情况时,会让i++,j=i,重新下一轮循环

但是我们发现,i后面的 1 1 0都会在j这个位置截停,无需多余的遍历

所以我们就可以使用滑动窗口,用left和right框住一个动态区间,内面的0的个数小于K

    解法二(滑动窗口) :

    算法思路 :

借用暴力算法的思想,不要去想怎么翻转,不要把问题想的很复杂,这道题的结果无非是一段连续的1中间塞了k个0嘛~

因此,我们可以把问题转化成: 求数组中一段最长的连续区间,要求这段区间内0的个数不超过k个

既然是连续区间,可以考虑使用[滑动窗口]来解决问题.

    图解流程 :

 

 

 

 

    代码展示 :

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

    结果分析 :

时间复杂度: O(N)

空间复杂度: O(1)

总的来说,用滑动窗口去解决这道题是非常高效的一种方法!

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值