算法每日双题精讲 —— 滑动窗口(水果成篮,找到字符串中所有字母异位词)

🌟快来参与讨论💬,点赞👍、收藏⭐、分享📤,共创活力社区。 🌟

别再犹豫了!快来订阅我们的算法每日双题精讲专栏,一起踏上算法学习的精彩之旅吧!💪

今天,咱们就一同来探究 “水果成篮” 和 “找到字符串中所有字母异位词” 这两道经典题目,看看滑动窗口算法是如何在其中施展魔法的🧙‍♂️。


目录

💯水果成篮

📖题目描述

🧠讲解算法原理

💻代码实现(以 C++ 为例)

💯找到字符串中所有字母异位词

📖题目描述

 🧠讲解算法原理

 💻代码实现(以 C++ 为例)


💯水果成篮


题目链接👉【力扣】

📖题目描述

根据示例分析,该题的本质就是:找出最长子数组的长度,子数组不超过俩种水果类型

🧠讲解算法原理

解法一:

 我们用暴力解法写一下,例如f=[1,2,3,2,2]

依次找出所以的情况👇

  1.  

代码中我们利用哈希表列举情况,用哈希表统计水果出现的类型数

解法二:

先分析

 当我们用暴力解法时,遇到如下情况👇,我们让 left++ ,right 回到 left的位置,继续列举情况

当left++时,区间的 kinds 要么不变,要么减少一个

  • 当kinds不变时,right没有必要改变
  • 当kinds减少时,right可以继续向后移动

 因此我们可以用滑动窗口的解法,right不回退嘛

滑动窗口四大步:

  1.  left=0,right=0
  2. 进窗口——right右移动的时候
  3. 判断    出窗口——就是left右移动的时候
  4. 更新结果

举例: f=[1,2,1,2,3,2,3,3]

每次遍历right,让其放入hash表里面,判断有没有超出类型个数

当hash.length>2时出窗口

left右移动的时候,要根据某个水果种类的数量来进行移动,因此我们创建的hash表要有俩个参数,一个记录种类,一个记录个数

例如下面👇,我们要将left移动到3的前面

💻代码实现(以 C++ 为例)

class Solution {
public:
    int totalFruit(vector<int>& fruits) 
    {
        int hash[100001]={0};//统计窗口内出现了多少种结果
        int ret=0;
        for(int left=0,right=0,kinds=0;right<fruits.size();right++)
        {
            if(hash[fruits[right]]==0) kinds++;
            hash[fruits[right]]++;//进窗口
            while(kinds>2)//判断
            {
                //出窗口
                hash[fruits[left]]--;
                if(hash[fruits[left]]==0)   kinds--;
                left++;
            }
            ret=max(ret,right-left+1);
        }
        return ret;
    }
};

💯找到字符串中所有字母异位词


题目链接👉【力扣】

📖题目描述

 

 🧠讲解算法原理

1.如何判断俩个字符串是否是异位词?

  • 可以先排序再比较,但是时间复杂度为nlogn ,比较大
  • 通过统计字符串中字符出现的个数也可以判断,借助hash表即可

 2.解决问题

例如

暴力解法: 

计入p的长度m ,在S里依次比较 

 

优化解法:

当字符串依次遍历时, ,我们发现ba重复出现,所以我们只要将c从hash表移除,让e加入hash表即可,滑动窗口

 

滑动窗口四大步:

  1.  left=0,right=0
  2. 进窗口——right右移动的时候
  3. 判断    出窗口——就是left右移动的时候
  4. 更新结果

 

3.优化:更新结果的判断条件

利用变量count来统计窗口中“有效字符”的个数

使用一个数组targetCount来记录字符串p中每个字母的出现次数,再使用一个数组windowCount来记录当前窗口内每个字母的出现次数。设一个变量valid来表示窗口内有效字母的数量,初始值为0。 

然后,将right指针向右移动,每移动一次,就将新字母在windowCount中的计数加1,并检查该字母的计数是否等于在targetCount中的计数,如果相等,则valid1。当valid等于p中不同字母的数量时,说明当前窗口是一个字母异位词。

 

此时,将left指针向右移动,同时更新windowCountvalid,直到valid小于p中不同字母的数量。在移动left指针的过程中,如果窗口内的子串长度等于p的长度,就将left指针的索引加入到结果数组中。

 

重复上述步骤,直到right指针走到字符串s的末尾。最后,返回结果数组。

 💻代码实现(以 C++ 为例)

class Solution {
public:
    vector<int> findAnagrams(string s, string p) {
        vector<int> result;
        // 如果s的长度小于p的长度,直接返回空结果
        if (s.length() < p.length()) return result;

        // 用于记录字符串p中每个字母的出现次数
        vector<int> targetCount(26, 0);
        // 用于记录当前窗口内每个字母的出现次数
        vector<int> windowCount(26, 0);
        int valid = 0;

        // 初始化targetCount数组
        for (char c : p) {
            targetCount[c - 'a']++;
        }

        int left = 0, right = 0;
        while (right < s.length()) {
            int rightIndex = s[right] - 'a';
            // 将新字母在windowCount中的计数加1
            windowCount[rightIndex]++;
            // 如果该字母的计数小于等于在targetCount中的计数,说明该字母在窗口内的数量还未超过p中该字母的数量,有效字母数量加1
            if (windowCount[rightIndex] <= targetCount[rightIndex]) {
                valid++;
            }

            // 当窗口大小大于p的长度时,移动left指针缩小窗口
            while (right - left + 1 > p.length()) {
                int leftIndex = s[left] - 'a';
                // 将left指针指向的字母在windowCount中的计数减1
                windowCount[leftIndex]--;
                // 如果该字母的计数小于在targetCount中的计数,说明该字母在窗口内的数量已经小于p中该字母的数量,有效字母数量减1
                if (windowCount[leftIndex] < targetCount[leftIndex]) {
                    valid--;
                }
                left++;
            }

            // 如果有效字母数量等于p中不同字母的数量,说明当前窗口是一个字母异位词,将left指针的索引加入结果数组
            if (valid == p.length()) {
                result.push_back(left);
            }

            right++;
        }

        return result;
    }
};

我以后还会对 算法 相关知识进行更多的创作,欢迎大家关注我,一起探索 算法 的奇妙世界😜

👉【A Charmer】

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于Qt事件机制中的定时器事件的闹钟设计

目标 代码 pro文件 QT core gui texttospeechgreaterThan(QT_MAJOR_VERSION, 4): QT widgetsCONFIG c11# The following define makes your compiler emit warnings if you use # any Qt feature that has been marked deprecated (the exact warnings # depend on …

后台管理系统DEMO

该项目后端使用SpringBootMyBatisPlusJWT&#xff0c;前端使用Vue3Vite2TSPiniaAxiosElementPlus等简单技术栈&#xff0c;实现了一个简约精致版的后台管理系统&#xff0c;包含非常基础的rbac权限功能&#xff0c;可以增删改查角色、用户、权限&#xff0c;角色添加权限、添加…

数据结构之线性表之链表(附加一个考研题)

链表的定义 链表的结构&#xff1a; 单链表-初始化 代码实现&#xff1a; 单链表-头插法 代码实现&#xff1a; 这里我给大家分析一下 我们每创建一个新的节点都要插在头节点的后面&#xff0c;我们一定要注意顺序 一定要先让新节点指向头节点指向的下一个节点&#xff0c;…

Python爬取城市天气信息,并存储到csv文件中

1.爬取的网址为&#xff1a;天气网 (weather.com.cn) 2.需要建立Weather.txt文件&#xff0c;并在里面加入如下形式的字段&#xff1a; 101120701济宁 101010100北京 3.代码运行后&#xff0c;在命令行输入Weather.txt文件中添加过的城市&#xff0c;如&#xff1a;济宁。 …

工厂+策略模式之最佳实践(疾病报卡维护模块API设计)

目录 &#x1f4bb;业务场景 &#x1f527;应用技术 ⚙概要流程 ❗开发注意 服务类上标注了 自定义注解 却无法直接利用getDeclaredAnnotation 获取 *Spring代理机制 代理机制的工作原理 代理的工作机制 代理的使用场景 已获取EmrXXXServiceImpl 的Class&#xff0c;…

【智行安全】基于Synaptics SL1680的AI疲劳驾驶检测方案

随著车载技术的快速进步&#xff0c;驾驶安全越来越受到重视&#xff0c;而疲劳驾驶是造成交通事故的重要原因之一。传统的驾驶监控技术因精度不足或反应迟缓&#xff0c;无法满足实时监测需求。因此&#xff0c;结合人工智能技术的疲劳驾驶检测系统成为行业新方向&#xff0c;…

Go-知识 注释

Go-知识 注释 行注释块注释包注释结构体&接口注释函数&方法注释废弃注释文档 在 go 语言中注释有两种&#xff0c;行注释和块注释 行注释 使用双斜线 // 开始&#xff0c;一般后面紧跟一个空格。行注释是Go语言中最常见的注释形式&#xff0c;在标准包中&#xff0c;…

2025年阿里云认证改版新消息!2025年阿里云认证考试内容有变!

阿里云认证已经确定在2025年要进行大改&#xff0c;这次改动幅度会比2023年改动更大&#xff0c;2023年主要改变是在考试题型上的变化&#xff0c;这次则主要是考试内容的变化了&#xff01; 2023年阿里云ACP认证考试的改版变化主要有&#xff1a; &#xff08;一&#xff09…

ArrayList 和LinkedList的区别比较

前言 ‌ArrayList和LinkedList的主要区别在于它们的底层数据结构、性能特点以及适用场景。‌ArrayList和LinkedList从名字分析&#xff0c;他们一个是Array&#xff08;动态数组&#xff09;的数据结构&#xff0c;一个是Linked&#xff08;链表&#xff09;的数据结构&#x…

STM32-笔记22-sg90舵机

一、接线 二、实验实现 动手让 SG90 每秒转动一下&#xff0c;0 -> 20 -> 40 -> 100 -> 180 如此循环。 舵机接A6 复制18-呼吸灯&#xff0c;重命名24-sg90舵机 把PWM重命名sg90 打开项目文件 在魔术棒和品上把PWM都去掉&#xff0c;加载sg90文件夹 加载之后…

QT集成intel RealSense 双目摄像头

最近一个小项目&#xff0c;用到了双目相机&#xff0c;选用了Intel的RealSense双目相机。功能很简单&#xff0c;就是识别某一个物体&#xff0c;然后对对这个物体进行操作。具体功能随后再说&#xff0c;这里只介绍QT如何集成IntelRealSense相机&#xff0c;就是下面这个。 首…

前端小案例——520表白信封

前言&#xff1a;我们在学习完了HTML和CSS之后&#xff0c;就会想着使用这两个东西去做一些小案例&#xff0c;不过又没有什么好的案例让我们去练手&#xff0c;本篇文章就提供里一个案例——520表白信封 ✨✨✨这里是秋刀鱼不做梦的BLOG ✨✨✨想要了解更多内容可以访问我的主…

Golang的发展历程

Golang的发展历程可以分为以下几个阶段&#xff1a; 设计阶段&#xff1a;2007年&#xff0c;Google开始研究开发一种新的编程语言&#xff0c;主要出于对C和Java等编程语言的不足之处的反思。经过一年多的研究和讨论&#xff0c;Golang的设计方案得到确定&#xff0c;主要包括…

硬件设计-硬件 EMC 设计规范

目录 引言&#xff1a; 常见原因 总体概念及考虑 布局 屏蔽 滤波 引言&#xff1a; 本规范只简绍 EMC 的主要原则与结论&#xff0c;为硬件工程师们在开发设计中抛砖引玉。 电磁干扰的三要素是干扰源、干扰传输途径、干扰接收器。EMC 就围绕这些 问题进行研究。最基本的…

后端开发-Maven

环境说明&#xff1a; windows系统&#xff1a;11版本 idea版本&#xff1a;2023.3.2 Maven 介绍 Apache Maven 是一个 Java 项目的构建管理和理解工具。Maven 使用一个项目对象模型&#xff08;POM&#xff09;&#xff0c;通过一组构建规则和约定来管理项目的构建&#xf…

C++ 编译过程全解析:从源码到可执行文件的蜕变之旅

引言 C 作为一种广泛应用于系统开发、游戏编程、嵌入式系统等领域的高级编程语言&#xff0c;其代码需要经过编译才能转换为计算机可执行的机器语言。编译过程涵盖多个复杂阶段&#xff0c;每个阶段对最终生成的可执行文件的性能、稳定性及兼容性都有着深远影响。深入理解 C 编…

数据库的概念和操作

目录 1、数据库的概念和操作 1.1 物理数据库 1. SQL SERVER 2014的三种文件类型 2. 数据库文件组 1.2 逻辑数据库 2、数据库的操作 2.1 T-SQL的语法格式 2.2 创建数据库 2.3 修改数据库 2.4 删除数据库 3、数据库的附加和分离 1、数据库的概念和操作 1.1 物理数据库…

【CSS in Depth 2 精译_096】16.4:CSS 中的三维变换 + 16.5:本章小结

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第五部分 添加动效 ✔️【第 16 章 变换】 ✔️ 16.1 旋转、平移、缩放与倾斜 16.1.1 变换原点的更改16.1.2 多重变换的设置16.1.3 单个变换属性的设置 16.2 变换在动效中的应用 16.2.1 放大图标&am…

期权懂|个股期权的流动性如何?

锦鲤三三每日分享期权知识&#xff0c;帮助期权新手及时有效地掌握即市趋势与新资讯&#xff01; 个股期权的流动性如何&#xff1f; 个股期权作为场外交易工具&#xff0c;具有较高的灵活性。场外交易意味着交易双方可以直接协商交易条款&#xff0c;这有助于满足不同投资者的…

关于在M系列的Mac中使用SoftEtherClient软件

1. 前言 本文说明的是在M系列的苹果的MacBook中如何使用SoftetherClient这款软件&#xff0c;是直接在MacOS操作系统中安装连接使用&#xff0c;不是在PD环境或者非ARM架构的Mac中安装使用。 PS&#xff1a;别费劲百度了&#xff0c;很少有相关解决方案的&#xff0c;在国内会…