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

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

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

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

目录

[1. 题目链接:](#1. 题目链接:)

[2. 题目描述 :](#2. 题目描述 :)

[3. 解法 :](#3. 解法 :)

[解法一(暴力枚举) :](#解法一(暴力枚举) :)

[算法思路 :](#算法思路 :)

[具体步骤 :](#具体步骤 :)

[代码展示 :](#代码展示 :)

[结果分析 :](#结果分析 :)

对暴力算法的反思与优化

[解法二(滑动窗口) :](#解法二(滑动窗口) :)

[算法思路 :](#算法思路 :)

[图解流程 :](#图解流程 :)

[代码展示 :](#代码展示 :)

[结果分析 :](#结果分析 :)


1. 题目链接:

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

2. 题目描述 :

给定一个二进制数组 nums 和一个整数 k,如果可以翻转最多 k0 ,则返回 数组中连续 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进入下一轮遍历

代码展示 :

cpp 复制代码
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个

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

图解流程 :

代码展示 :

cpp 复制代码
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)

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

相关推荐
用户0099383143014 分钟前
代码随想录算法训练营第十三天 | 二叉树part01
数据结构·算法
shinelord明8 分钟前
【再谈设计模式】享元模式~对象共享的优化妙手
开发语言·数据结构·算法·设计模式·软件工程
დ旧言~14 分钟前
专题八:背包问题
算法·leetcode·动态规划·推荐算法
_WndProc31 分钟前
C++ 日志输出
开发语言·c++·算法
薄荷故人_33 分钟前
从零开始的C++之旅——红黑树及其实现
数据结构·c++
努力学习编程的伍大侠44 分钟前
基础排序算法
数据结构·c++·算法
XiaoLeisj1 小时前
【递归,搜索与回溯算法 & 综合练习】深入理解暴搜决策树:递归,搜索与回溯算法综合小专题(二)
数据结构·算法·leetcode·决策树·深度优先·剪枝
Jasmine_llq2 小时前
《 火星人 》
算法·青少年编程·c#
闻缺陷则喜何志丹2 小时前
【C++动态规划 图论】3243. 新增道路查询后的最短距离 I|1567
c++·算法·动态规划·力扣·图论·最短路·路径