基础算法(5):滑动窗口

news2024/11/25 14:30:12

1.何为滑动窗口?

     滑动窗口其实也是一种算法,主要有两类:一类是固定窗口,一类是可变窗口。固定的窗口只需要一个变量记录,而可变窗口需要两个变量。

2.固定窗口

     就像上面这个图一样。两个相邻的长度为4的红色窗口,下一个窗口一定比前一个窗口少一个数据,以及多一个数据。

      橙色为切换窗口时少的那个数据,黄色为多出来的那个数据,所以可以直接沿用之前数据,并且减去橙色数据,加上黄色数据,就是下一个窗口的值了。这就是滑动窗口的一个经典思路。

2.1 例题解析

      首先题是这样的

给你一个整数数组arr和两个整数k和target。请你返回长度为k且平均值大于等于target的子数组数目。

       我们可以看到他已经确定了窗口的长度,像这种滑动窗口的问题,一般都是连续字串和连续子数组的问题,在我做过的题中还没有例外,这也是滑动窗口的应用限制,必须连续。下面让我们看看怎么写:

       (1)首先,统计前k个数的和sum,作为第一个窗口的值,并且判断是否满足sum>=target,如果满足,则计数器加一;

       (2)然后,窗口开始右移,以后每次通过前一个相邻窗口,计算得到下一个窗口的值,并且判断条件是否满足满足则计数器加一;

       (3)返回计数器的值;

nclude<iostream>
int numOfSubarrays(int* arr, int arrSize, int k, int target)
{
    int r;
    int sum = 0;
    int cnt = 0;
    for (r = 0; r < k; r++)
    {
        sum += arr[r];
    }
    if (sum >= target)cnt++;

    for (r = k; r < arrSize; r++)
    {
        sum -= arr[r - k];
        sum += arr[r];
        if (sum >= target)cnt++;
    }
    return cnt;
}

2.2 leetcode固定窗口题目及模板总结

2.2.1 定长字串中元音的最大数目  
class Solution {
public:
    int check(char c)//每次遇到一个字符都需要进行判断,所以我们自己实现一个函数,避免重复代码
    {
         if(c=='a'||c=='e'||c=='i'||c=='o'||c=='u')
         {
             return 1;
         }
         return 0;
    }
    int maxVowels(string s, int k) {
    int n=s.size();
    int r=0;//窗口边界
    int cnt=0;//计数器
    int sum=0;//比较迭代的变量
    for(;r<n;r++)//开始遍历
    {
       cnt+=check(s[r]);//向窗口内添加元素
       if(r>=k)//窗口长度大于给定值
        {
            cnt-=check(s[r-k]);滑动直到长度等于k,减去左边元素,向右不断滑动
        }
        sum=max(sum,cnt);//将sum和cnt的值进行比较,这里sum其实起到了比较作用,将cnt的值存储到sum中
    }
    return sum;
    }
};
2.2.2 长度最小的子数组

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int r;
        int result=INT32_MAX;
        int sum=0;
        int i=0;
        for(r=0;r<nums.size();r++)
        {
            sum+=nums[r];
            while(sum>=target){
                result=min(result,r-i+1);
                sum-=nums[i++];
            }
        }
        return result==INT32_MAX?0:result;
    }
};

       从这两道题中我们看到了一些相似的代码,这就是

2.2.3 固定窗口长度模板
int subarrays(int* arr, int k, int target)
{ 
    int n=arr.size();//数组长度
    int r;//窗口边界
    int cnt = 0;//一般用来求和或者计数,视题目而定
    int sum = 0;//比较迭代的变量
    for (; r < n; r++)//开始遍历
    {
        cnt += arr[r];//向窗口内添加元素
        if (r >= k)//窗口长度大于给定值
        {
            cnt -= arr[r - k]; //减去左边元素,向右不断滑动,直到长度等于k
        }
        sum = max(sum, cnt);//更新sum的值,将sum和cnt的值进行比较,这里sum其实起到了比较作用,将cnt的值存储到sum中
    }
    return sum;
}

3.非固定窗口

3.1 例题解析

给定一个二进制数组 nums 和一个整数 k,如果可以翻转最多 k 个 0 ,则返回 数组中连续 1 的最大个数 。

     这个题怎么写呢?这个可没有说求固定长度,你翻转最多k个0之后连续1的长度最大,这个长度就是数组中连续1的最大个数,那我们就把固定长度不固定就ok了啊,下面看代码解析:

int longestOnes(vector<int>& nums, int k) {
     int n=nums.size();//数组/字符串长度
     int sum=0;//用于统计子数组/子区间是否有效,看题目要求,可能是求和/计数
     int l=0;//双指针,代表遍历的区间
     int zerocnt=0;//统计0的个数
     for(int r=0;r<n;r++)
     {
         if(nums[r]==0)zerocnt++;//满足题目要求,计数器+1
         while(zerocnt>k)//翻转0的个数大于k
         {
            if(nums[l++]==0)zerocnt--;//那就开始滑动窗口了,左边界开始滑动,这时候需要判断左边界的数是不是0,是0则计数器-1,滑动到计数器的值等于k
         }
         sum=max(sum,r-l+1);//更新sum的值
     }
     return sum;
    }
};

     相信看完代码之后大家会发现,固定长度的滑动窗口,while循环的条件都是比较长度,而非固定长度的滑动窗口,虽然不是比较长度,但也有其他的条件进行限制,具体什么条件就需要看具体的题目了。

3.2 leetcode非固定窗口题目及模板总结

3.2.1 字符串的排列

class Solution {
public:
    bool checkInclusion(string s1, string s2) {
        //滑动窗口
        unordered_map<char, int> win, need;
        //将子串的元素压入哈希表
        for (auto &i : s1){
            ++need[i];
        }
        //定义边界
        int right = 0, left = 0, n = s1.size(), num = s2.size(), count = 0;
        //进行滑动窗口
        for(;right < num;right++){
            //如果可以在哈希表中找到元素就压入到窗口中
            if (need.find(s2[right]) != need.end()){
                ++win[s2[right]];
                if (need[s2[right]] == win[s2[right]]){
                    ++count;
                }
            }
            while(right - left + 1 >= n){
                if (count == need.size()){
                    return true;
                }
                //缩小窗口
                if (need.find(s2[left]) != need.end()){
                    //缩小窗口的步骤其实跟扩大窗口的步骤是相反的
                    if (need[s2[left]] == win[s2[left]]){
                        --count;
                    }
                    --win[s2[left]];
                }
                left++;
            }
        }
        return false;
    }
};
3.2.2 最短超串

class Solution {
public:
    vector<int> shortestSeq(vector<int>& big, vector<int>& small) {
       int n=big.size();//数组长度
       unordered_map<int,int>win,need;//定义两个哈希表,一个存储子数组,一个存储窗口
       for(auto a:small)//将子数组压入哈希表中便于查找和比较
       {
           need[a]++;
       }
       int l=0,r=0;//定义双指针(变量)作边界
       vector<int>ans;//定义一个数组用来存储最短子数组的左端点和右端点
       int count=0;//计数器,用来计算长数组出现子数组元素的次数,便于条件处理
       int len=INT_MAX;//可以不断更新的长度len
       //开始滑动窗口
       for(;r<n;r++)
       {
           //扩大窗口
           if(need.find(big[r])!=need.end())
           {
             win[big[r]]++;
             if(need[big[r]]==win[big[r]])//防止重复
             {
                count++;  
             }
           }
           //开始缩小窗口
           while(count==need.size())
          {
             //进行获取最短超串
             if(len>r-l+1)//判断下一个窗口是否比上一个窗口长度小,如果小则更新len和ans数组的值
             {
                 ans={l,r};
                 len=r-l+1;
             }
              如果此时窗口左端的值在子数组的哈希表中耀进行特殊处理
             if(need.find(big[l])!=need.end())
             {
                
                 if(need[big[l]]==win[big[l]])
                 {
                     count--;
                 }
                 win[big[l]]--;
             }
             l++;
          }
       }
       return ans;
    }
};
3.3.3 非固定窗口模板
int slidingWindow(vector<int> nums) {
    int n = nums.size();
    int ans = 0;
    // 记录窗口内的元素及其个数,非必要
    map<int, int> um;
    // l:窗口左边界; r:窗口右边界
    int l = 0, r = 0;
    // r 指针负责探索新的区间,直到搜索到nums的某末尾
    for(;r < n;r++) {
        um[r]++;
        // 如果区间不满足条件,l指针右移,窗口收缩
        while (区间[l, r] is Invalid) {
            um[l]--;
            l++;
        }
        // 此处处理结果, deal with(ans, 区间[l, r])
        res = max(ans, r - l + 1); // 或者res = min(ans, r - l + 1);
    }
    return ans;
}

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

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

相关文章

HTML---CSS美化网页元素

文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 一.div 标签&#xff1a; <div>是HTML中的一个常用标签&#xff0c;用于定义HTML文档中的一个区块&#xff08;或一个容器&#xff09;。它可以包含其他HTML元素&#xff0c;如文本、图像…

探秘 AJAX:让网页变得更智能的异步技术(上)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

如何编写好的测试用例?

对于软件测试工程师来说&#xff0c;设计测试用例和提交缺陷报告是最基本的职业技能。是非常重要的部分。一个好的测试用例能够指示测试人员如何对软件进行测试。在这篇文章中&#xff0c;我们将介绍测试用例设计常用的几种方法&#xff0c;以及如何编写高效的测试用例。 一、…

iPhone 17Pro/Max或升级4800万像素长焦镜头,配备自研Wi-Fi 7芯片。

iPhone 16未至&#xff0c;关于iPhone 17系列的相关消息就已经放出&#xff0c;到底是谁走漏了风声。 海通国际证券技术分析师Jeff Pu近日发布报告称&#xff0c;苹果将为2025年推出的iPhone 17ProMax配备4800万像素的长焦镜头。经调查&#xff0c;该分析师认为提升iPhone拍摄方…

如何在华为云上购买ECS及以镜像的方式部署华为云欧拉操作系统 (HCE OS)

写在前面 工作中遇到&#xff0c;简单整理博文内容为 华为云开发者认证 实验笔记https://edu.huaweicloud.com/certificationindex/developer/9bf91efb086a448ab4331a2f53a4d3a1理解不足小伙伴帮忙指正 对每个人而言&#xff0c;真正的职责只有一个&#xff1a;找到自我。然后在…

Nginx快速入门:Nginx应用场景、安装与部署(一)

1. Nginx简介 Nginx 是一个高性能的 HTTP 和反向代理服务器&#xff0c;也是一个非常流行的开源 Web 服务器软件。它是由俄罗斯程序员 Igor Sysoev 开发的&#xff0c;最初是为了解决在高并发场景下的C10k 问题&#xff08;即一个服务器进程只能处理 10,000 个并发连接&#x…

早期的OCR是怎么识别图片上的文字的?

现在的OCR技术融合了人工智能技术&#xff0c;通过深度学习&#xff0c;无论是识别的准确率还是效果都非常不错&#xff0c;那您知道在早期的OCR是通过什么技术来实现的吗&#xff1f;如果您不知道&#xff0c;那么&#xff0c;就让我来告诉您&#xff1a;它主要是基于字符的几…

DiffUtil + RecyclerView 在 Kotlin中的使用

很惭愧, 做了多年的Android开发还没有使用过DiffUtil这样解放双手的工具。 文章目录 1 DiffUtil 用来解决什么问题?2 DiffUtil 是什么?3 DiffUtil的使用4 参考文章 1 DiffUtil 用来解决什么问题? 先举几个实际开发中的例子帮助我们感受下: 加载内容流时,第一次加载了ABC,…

数据分析思维导图

参考&#xff1a; https://zhuanlan.zhihu.com/p/567761684?utm_id0 1、数据分析步骤地图 2、数据分析基础知识地图 3、数据分析技术知识地图 4、数据分析业务流程 5、数据分析师能力体系 6、数据分析思路体系 7、电商数据分析核心主题 8、数据科学技能书知识地图 9、数据挖掘…

文章解读与仿真程序复现思路——电力系统自动化EI\CSCD\北大核心《基于碳捕集-电转气的矿区综合能源系统协同优化调度》

这个标题涉及到碳捕集、电力转化为气体&#xff08;可能是指电力转化为氢气等&#xff09;、矿区综合能源系统以及协同优化调度等概念。让我们逐步解读&#xff1a; 碳捕集&#xff08;Carbon Capture&#xff09;&#xff1a; 这指的是通过不同技术手段捕获和隔离工业过程中产…

输电线路定位:精确导航,确保电力传输安全

在现代社会中&#xff0c;电力作为生活的基石&#xff0c;其安全稳定运行至关重要。而输电线路作为电力传输的重要通道&#xff0c;其故障定位和修复显得尤为重要。恒峰智慧科技将为您介绍一种采用分布式行波测量技术的输电线路定位方法&#xff0c;以提高故障定位精度&#xf…

新版Android Studio Logcat 筛选日志

下载了新版的Android Studio&#xff0c;android-studio-2022.3.1.21-mac_arm&#xff0c;记录一下新版本AS的logcat过滤日志条件 1. 按照包名过滤 1.1 过滤当前包名的日志 package:mine 1.2 过滤其他包名日志 package:com.example.firstemptyapplication 2. 按照日志等级过滤…

STM32与Freertos入门(三)任务的创建、删除

1、串口配置 首先将串口进行配置&#xff0c;后续经常会应用&#xff0c;具体步骤点击&#xff1a;串口配置。 2、任务 创建一个任务&#xff0c;就是开辟一个空间、每个任务中都会有while&#xff08;1&#xff09;死循环。 2.1相关函数 动态创建&#xff1a;xTaskCreate…

Github 2023-12-19开源项目日报 Top10

根据Github Trendings的统计&#xff0c;今日(2023-12-19统计)共有10个项目上榜。根据开发语言中项目的数量&#xff0c;汇总情况如下&#xff1a; 开发语言项目数量Python项目4Rust项目2非开发语言项目2C#项目1TypeScript项目1 Avalonia: 跨平台UI框架和Avalonia XPF 创建周…

20231218给Firefly的AIO-3399J【RK3399】开发板刷Android12挖掘机方案

20231218给Firefly的AIO-3399J【RK3399】开发板刷Android12挖掘机方案 2023/12/18 21:07 一、整体编译Rockchip的的Android12的挖掘机方案&#xff01; 由于RK3399的Android12系统默认是IND工业方案&#xff0c;需要修改一下【为挖掘机方案】。 Z:\3TB\81rk_android12_220722\…

鸿蒙端H5容器化建设——JSB通信机制建设

1. 背景 2023年鸿蒙开发者大会上&#xff0c;华为宣布为了应对国外技术封锁的潜在风险&#xff0c;2024年的HarmonyOS NEXT版本中将不再兼容Android&#xff0c;并推出鸿蒙系统以及其自研的开发框架&#xff0c;形成开发生态闭环。同时&#xff0c;在更高维度上华为希望将鸿蒙…

NVMe over CXL技术如何加速Host与SSD数据传输?

在现代计算环境中&#xff0c;优化Host&#xff08;主机&#xff09;与device&#xff08;设备&#xff09;之间的数据传输速度对于提升系统整体性能和效率至关重要。目前业内主要有以下几种方案&#xff1a; Controller Memory Buffer (CMB)&#xff1a; CMB是一种集成在NVMe …

Python数据科学视频讲解:Python数据缺失值处理

3.5 Python数据缺失值处理 视频为《Python数据科学应用从入门到精通》张甜 杨维忠 清华大学出版社一书的随书赠送视频讲解3.5节内容。本书已正式出版上市&#xff0c;当当、京东、淘宝等平台热销中&#xff0c;搜索书名即可。内容涵盖数据科学应用的全流程&#xff0c;包括数据…

数据库增删改查Native SQL

DBCO&#xff1a;检查数据库是否连接 代码&#xff1a; 查询&#xff1a; DATA: gv_dbs TYPE char30 VALUE XXXXXXXX. "数据库连接名称 DATA:gt_ztclaim_2 TYPE TABLE OF ztclaim_2. DATA:gs_ztclaim_2 TYPE ztclaim_2.TRY.EXEC SQL.CONNECT TO :GV_DBSENDEXEC.EXEC SQ…

【计算机网络】TCP协议——2.连接管理(三次握手,四次挥手)

目录 前言 一. 建立连接——三次握手 1. 三次握手过程描述 2. TCP连接建立相关问题 二. 释放连接——四次挥手 1. 四次挥手过程描述 2. TCP连接释放相关问题 三. TCP状态转换 结束语 前言 TCP——传输控制协议(Transmission Control Protocol)。是一种面向连接的传…