[算法] 优先算法(三):滑动窗口(上)

news2024/9/23 3:19:14

🌸个人主页:https://blog.csdn.net/2301_80050796?spm=1000.2115.3001.5343
🏵️热门专栏:🍕 Collection与数据结构 (92平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm=1001.2014.3001.5482
🧀Java EE(94平均质量分) https://blog.csdn.net/2301_80050796/category_12643370.html?spm=1001.2014.3001.5482
🍭MySql数据库(93平均质量分)https://blog.csdn.net/2301_80050796/category_12629890.html?spm=1001.2014.3001.5482
🍬算法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12676091.html?spm=1001.2014.3001.5482
感谢点赞与关注~~~
在这里插入图片描述

目录

  • 1. 概述
  • 2. 长度最小的子数组(难度:🔵2度)
  • 3. 无重复字符的最长子串(难度:🔵2度)
  • 4. 最大连续1的个数III(难度:🟡3度)
  • 5. 将x减到0的最小操作数(难度:🟡3度)

1. 概述

所谓滑动窗口,也叫通向双指针,就是在我们上一个板块双指针的基础上,把双指针的"点"变换成"线",双指针表示两个点,而滑动窗口则是由双指针的两个"点"构成"线",表示一个区间.
滑动窗口最基本有以下几步的操作:

  1. 指定left=0right=0两个左右指针.
  2. 让右指针右移,进入窗口.
  3. 让左指针右移,出窗口.
  4. 更新结果,结果在哪一步更新不确定,需要具体问题具体分析.

2. 长度最小的子数组(难度:🔵2度)

OJ链接

  • 题目描述

给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其总和大于等于 target 的长度最小的 连续
子数组
[numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
示例 1:
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。
示例 2:
输入:target = 4, nums = [1,4,4]
输出:1
示例 3:
输入:target = 11, nums = [1,1,1,1,1,1,1,1]
输出:0

  • 算法原理
    由于此问题分析的对象是「⼀段连续的区间」,因此可以考虑「滑动窗⼝」的思想来解决这道题。
    让滑动窗⼝满⾜:从i 位置开始,窗⼝内所有元素的和⼩于target (那么当窗⼝内元素之和
    第⼀次⼤于等于⽬标值的时候,就是i 位置开始,满⾜条件的最⼩⻓度
    )。
    做法:将右端元素划⼊窗⼝中,统计出此时窗⼝内元素的和:
    • 如果窗⼝内元素之和⼤于等于target :更新结果,并且将左端元素划出去的同时继续判
      断是否满⾜条件并更新结果
      (因为左端元素可能很⼩,划出去之后依旧满⾜条件)
    • 如果窗⼝内元素之和不满⾜条件: right++ ,另下⼀个元素进⼊窗⼝。
  • 为什么滑动窗口可以保证最终结果的正确性,而且时间复杂度很低?
    • 这个窗⼝寻找的是:以当前窗口最左侧元素(记为left1 )为基准,符合条件的情况。也
      就是在这道题中,从left1 开始,满⾜区间和sum >= target 时的最右侧(记为right1 )能到哪⾥。
    • 我们既然已经找到从left1 开始的最优的区间,那么就可以大胆舍去left1 。但是如
      果使用暴力解法,重新开始统计第⼆个元素( left2 )往后的和,势必会有⼤量重复
      的计算(因为我们在求第⼀段区间的时候,已经算出很多元素的和了,这些和是可以在计算
      下次区间和的时候用上的
      )。
    • 此时, rigth1 的作⽤就体现出来了,我们只需将left1 这个值从sum 中剔除
      right1 这个元素开始,往后找满足left2 元素的区间
      (此时right1 也有可能是满
      ⾜的,因为left1 可能很⼩。 sum 剔除掉left1 之后,依旧满⾜⼤于等于
      target )。这样我们就能省掉⼤量重复的计算。
    • 这样我们不仅能解决问题,⽽且效率也会⼤⼤提升。
      时间复杂度:虽然代码是两层循环,但是我们的left 指针和right 指针都是不回退的,两者
      最多都往后移动n 次。因此时间复杂度是O(N) 。
    • 最后需要注意的一点就是,在一开始定义len的时候,由于题目中让我们找的是最小值,所以我们在给len赋值的时候,要赋值的是Integer的最大值.如果赋值为0,结果会一直是0.
  • 代码编写
class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int left = 0;
        int right = 0;
        int len = Integer.MAX_VALUE;//这里之所以要定义整数的最大值,是因为后面计算最小值的
        //时候,如果赋值为0,就一直是0
        int sum = 0;
        for (;right < nums.length;right++){
            sum += nums[right];
            while (sum >= target){
                len = Math.min(len,right - left + 1);//在刚好到达最小长度的时候,更新长度
                //之后出窗口的时候一直更新,直到不满足循环条件
                sum -= nums[left];
                left++;
            }
        }
        return len == Integer.MAX_VALUE? 0:len;
    }
}

3. 无重复字符的最长子串(难度:🔵2度)

OJ链接

  • 题目描述

给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串
的长度。
示例 1:
输入: s = “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:
输入: s = “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:
输入: s = “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。

  • 算法原理
    研究对象依然是一段区间,所以我们考虑使用滑动窗口.
    1. 定义Set来统计子串中都有哪些字符.
    2. 每有一个字符进入窗口,就判断个字符在不在Set中.
    3. 如果在,就让通过移动left指针让前面的元素出窗口,每出一个,就从Set中删除一个字符,直到Set中没有right指针指向的这个字符为止.
    4. 如果不在,就进入窗口,让Set中也增加这个字符.
  • 代码编写
class Solution {
    public int lengthOfLongestSubstring(String s) {
        Set<Character> set = new HashSet<>();//定义Set,用来统计区间内的字符
        int left = 0;
        int right = 0;
        int len = 0;
        for (;right < s.length();right++){
            while (set.contains(s.charAt(right))){//判断元素是否在区间中出现过
                set.remove(s.charAt(left));//每有元素出窗口,就从Set中删除
                left++;
            }
            set.add(s.charAt(right));//每有元素进入窗口,就加入Set
            len = Math.max(len,right-left+1);
        }
        return len;
    }
}

4. 最大连续1的个数III(难度:🟡3度)

OJ链接

  • 题目描述

给定一个二进制数组 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转化为1
    • 因此,我们可以把问题转化成:求数组中⼀段最⻓的连续区间,要求这段区间内0 的个数不超过k 个。既然是连续区间,可以考虑使⽤「滑动窗口」来解决问题。
    • 让数组中的元素进入窗口,每进入一次窗口,就让表示最大长度的len++,如果进入的元素是0,那么就让统计0个数的zero++,当zero的个数大于了规定个数,就让区间之前的元素出窗口,直到0恢复正常个数.
  • 代码编写
class Solution {
    public int longestOnes(int[] nums, int k) {
        int left = 0;
        int right = 0;
        int len = 0;
        int zero = 0;
        for (;right < nums.length;right++){
            if (nums[right] == 0){
                zero++;
            }
            while (zero > k){
                if (nums[left] == 0){
                    zero--;
                }
                left++;
            }
            len = Math.max(len,right-left+1);
        }
        return len;
    }
}

5. 将x减到0的最小操作数(难度:🟡3度)

OJ链接

  • 题目描述

给你一个整数数组 nums 和一个整数 x 。每一次操作时,你应当移除数组 nums 最左边或最右边的元素,然后从 x 中减去该元素的值。请注意,需要 修改 数组以供接下来的操作使用。
如果可以将 x 恰好 减到 0 ,返回 最小操作数 ;否则,返回 -1 。
示例 1:
输入:nums = [1,1,4,2,3], x = 5
输出:2
解释:最佳解决方案是移除后两个元素,将 x 减到 0 。
示例 2:
输入:nums = [5,6,7,8,9], x = 4
输出:-1
示例 3:
输入:nums = [3,2,20,1,1,3], x = 10
输出:5
解释:最佳解决方案是移除后三个元素和前两个元素(总共 5 次操作),将 x 减到 0 。

  • 算法原理
    • 这道题最不好想的一点就是:这里的区间是数组两边的两个不连续的短区间,那么我们就有一种解决问题的办法正难则反.我们可以考虑把两个短区间通过使用数组长度减去,变成一个长区间.转化成求数组内⼀段连续的、和为 sum(nums) - x 的最长数组。此时,就是熟悉的「滑动窗⼝」问题了。
    • a. 转化问题:求target = sum(nums) - x 。如果target < 0 ,问题⽆解;也就是说,本用例即使把数组中所有的数字全部用上了,也达不到要求的那个值.
      b. 初始化左右指针l = 0 ,r = 0 (滑动窗⼝区间表⽰为[l, r) ,左右区间是否开闭很重要,必须设定与代码⼀致),记录当前滑动窗⼝内数组和的变量sum = 0 ,记录当前满⾜条件数组的最⼤区间⻓度maxLen = -1 ;
      c. 当 r ⼩于等于数组⻓度时,⼀直循环:i. 如果sum < target ,右移右指针,直⾄变量和⼤于等于target ,或右指针已经移到头;
      ii. 如果sum > target ,右移左指针,直⾄变量和⼩于等于target ,或左指针已经移到
      头;
      iii. 如果经过前两步的左右移动使得sum == target ,修改满足条件数组的最大长度,并
      让下个元素进入窗口

      d. 循环结束后,如果maxLen 的值有意义,则计算结果返回;否则,返回 -1 。
  • 代码编写
class Solution {
    public int minOperations(int[] nums, int x) {
        int left = 0;
        int right = 0;
        int sum = 0;
        int sum1 = 0;
        int len = -1;
        for (int num:nums){
            sum += num;
        }
        int target = sum - x;
        if (target < 0){//如果数组的总和都不够达到x的,那么就不存在这样的数字
        //直接返回-1
            return -1;
        }
        for (;right < nums.length;right++){
            sum1 += nums[right];
            while (sum1 > target){
                sum1 -= nums[left];
                left++;
            }
            if (sum1 == target){
                len = Math.max(len,right-left+1);
            }
        }
        if (len == -1){
            return len;
        }else{
            return nums.length-len; 
        }
        
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1701942.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Docker安装Oracle11g数据库

操作系统&#xff1a;centOS9使用此方法检查是否安装Docker&#xff1a;docker --help&#xff0c;如果有帮助文件则证明安装成功使用此语句检查Docker是否正在运行&#xff1a;docker images&#xff0c;实际上是查看本地镜像如果发现未运行则开启Docker&#xff1a;systemctl…

Linux 36.3@Jetson Orin Nano之系统安装

Linux 36.3Jetson Orin Nano之系统安装 1. 源由2. 命令行烧录Step 1&#xff1a;下载Linux 36.3安装程序Step 2&#xff1a;下载Linux 36.3根文件系统Step 3&#xff1a;解压Linux 36.3安装程序Step 4&#xff1a;解压Linux 36.3根文件系统Step 5&#xff1a;安装应用程序Step …

突发!某大厂机房掉电,MySQL数据库无法启动,紧急恢复过程...

作者&#xff1a;IT邦德 中国DBA联盟(ACDU)成员&#xff0c;10余年DBA工作经验&#xff0c; Oracle、PostgreSQL ACE CSDN博客专家及B站知名UP主&#xff0c;全网粉丝10万 擅长主流Oracle、MySQL、PG、高斯及Greenplum备份恢复&#xff0c; 安装迁移&#xff0c;性能优化、故障…

类和对象03

六、继承 我们发现&#xff0c;定义这些类时&#xff0c;下级别的成员除了拥有上一级的共性&#xff0c;还有自己的特性。 这个时候我们就可以考虑利用继承的技术&#xff0c;减少重复代码 6.1 继承的基础语法 例如我们看到很多网站中, 都有公共的头部&#xff0c;公共的底…

数据结构—二叉树相关概念【详解】【画图演示】

P. S.&#xff1a;以下代码均在VS2019环境下测试&#xff0c;不代表所有编译器均可通过。 P. S.&#xff1a;测试代码均未展示头文件stdio.h的声明&#xff0c;使用时请自行添加。 目录 1、二叉树的概念及结构1、1 二叉树的概念1、2 二叉树的结构 2、特殊的二叉树3、二叉树的性…

【Hive SQL 每日一题】行列转换

文章目录 行转列列传行 行转列 测试数据&#xff1a; DROP TABLE IF EXISTS student_scores;CREATE TABLE student_scores (student_id INT,subject STRING,score INT );INSERT INTO student_scores (student_id, subject, score) VALUES (1, Math, 85), (1, English, 78), (…

光纤跳线组成结构划分你知道吗

按照组成结构划分 光纤跳线根据组成结构的不同可分为带状光纤跳线和束状光纤跳线。带状光纤跳线使用的是由光纤带组成的带状光缆&#xff0c;大多呈扁平形状&#xff0c;因具有较高的光纤密度&#xff0c;它可以容纳更多的纤芯&#xff0c;因此大大节省布线成本和空间&#xf…

JavaScript 新特性:新增声明命令与解构赋值的强大功能

个人主页&#xff1a;学习前端的小z 个人专栏&#xff1a;JavaScript 精粹 本专栏旨在分享记录每日学习的前端知识和学习笔记的归纳总结&#xff0c;欢迎大家在评论区交流讨论&#xff01; ES5、ES6介绍 文章目录 &#x1f4af;声明命令 let、const&#x1f35f;1 let声明符&a…

VMware虚拟机如何与主机共享文件夹

本机:WIN10 VMware虚拟机:WIN7 因为每次配置都爱忘记操作,目标是为了在WIN7虚拟机中可以访问本机文件 首先本机操作 新建一个共享文件夹,不带中文目录(最好不要) 点击共享 选择everyone,记得权限"读取和写入" 然后到虚拟机里面 添加一个网络位置 点击浏览,选择网…

刷题之从前序遍历与中序遍历序列构造二叉树(leetcode)

从前序遍历与中序遍历序列构造二叉树 前序遍历&#xff1a;中左右 中序遍历&#xff1a;左中右 前序遍历的第一个数必定为根节点&#xff0c;再到中序遍历中找到该数&#xff0c;数的左边是左子树&#xff0c;右边是右子树&#xff0c;进行递归即可。 #include<vector>…

ChatGPT-4o模型功能介绍——还没用过的看过来

1.概述 OpenAI 持续突破人工智能的边界&#xff0c;推出了其最新模型 ChatGPT-4o&#xff0c;作为 ChatGPT-4 的继承者&#xff0c;该模型有望带来显著的提升和创新功能。本文将深入解析 ChatGPT-4 与 ChatGPT-4o 之间的区别&#xff0c;并探讨它们的功能、性能以及潜在的应用…

5.22 R语言-正态性检验

正态性检验 正态性检验的目的是确定一组数据是否符合正态分布&#xff08;也称高斯分布&#xff09;。在统计分析和数据建模中&#xff0c;正态性假设是许多统计方法和模型的基础。了解数据是否符合正态分布有助于选择适当的统计方法和确保分析结果的有效性。 本文主要从概率…

神秘山洞惊现AI绘画至宝Stable Diffusion残卷

最近听到不少大宗门纷纷发声&#xff1a;随着AI神器的现世“程序员职业将不复存在”&#xff0c;“设计师将要失业”。 至此&#xff0c;不少修士开始担忧起来&#xff0c;现出世的AI神器会不会取代掉我辈修士。 其实&#xff0c;至女娲天神创造人类以来&#xff0c;在这漫漫…

RabbitMQ 交换机类型

常用交换机 发布订阅&#xff08;Publish/Subscribe&#xff09;交换机 一个生产者给多个队列发送消息&#xff0c;X 代表交换机。 交换机的作用&#xff1a;类似网络路由器&#xff0c;主要提供转发功能&#xff0c;解决怎么把消息转发到不同的队列中&#xff0c;让消费者从不…

基于Java+MySQL+Swing的学生管理系统

1.系统简介和开发背景 该同学工作积极主动、高效&#xff0c;学习认真&#xff0c;待人诚恳&#xff0c;能够做到服从指挥、认真听取老同志的指导&#xff0c;不怕苦、不怕累&#xff0c;表现有较强的求知欲&#xff0c;积极观察、体验、思考&#xff0c;并能够灵活运用自己的知…

Web安全技术期末考查-vulhub靶场搭建及漏洞复现

一、实验目的与要求 能根据报告找到难度适中的漏洞&#xff0c;搭建弱点环境&#xff0c;并验证该漏洞&#xff1b; 2.能给出该漏洞的修复建议。 二、实验原理与内容 漏洞原理 漏洞原理通常指的是计算机系统、软件、网络或其他技术系统中存在的安全缺陷&#xff0c;这些缺陷…

rapidssl泛域名https600元一年

泛域名https证书也可以称之为通配符https证书&#xff0c;指的是可以用一张https证书为多个网站(主域名以及主域名下的所有子域名网站)传输数据加密&#xff0c;并且提供身份认证服务的数字证书产品。RapidSSL旗下的泛域名https证书性价比高&#xff0c;申请速度快&#xff0c;…

浅谈JMeter体系结构

JMeter体系结构详解 JMeter是一款功能强大的开源性能测试工具&#xff0c;广泛应用于Web应用、数据库、FTP服务器等多种场景下的负载和压力测试。其灵活的体系结构设计使得测试计划的创建、执行与结果分析变得高效而直观。本文将深入解析JMeter的三维空间体系结构&#xff0c;…

SSE(Server Sent Event) 踩坑留念

整条链路是 客户端A --> 服务端 A —> 服务端 B 我负责服务端 A 此时要注意 Client 中的 processes 的写法 Post(value “/v2/xx”, processes MediaType.TEXT_EVENT_STREAM) 这样写是一直报错的 改成下面的写法才可以 Post(value “/v2/xx”, processes MediaT…

HTTP 协议的基本格式和Fidder的简单使用

HTTP协议诞生于1996&#xff08;开玩笑哈&#xff0c;诞生于1991年&#xff09;&#xff0c;http协议用于网页和手机app和服务器交互的场景。通过HTTP协议&#xff0c;客户端&#xff08;例如网页浏览器或手机应用&#xff09;可以向服务器发送请求&#xff0c;服务器则会响应这…