【优选算法 — 滑动窗口】水果成篮 找到字符串中所有字母异位词

   

 


  水果成篮  


水果成篮


 

  题目描述  

因为只有两个篮子,每个篮子装的水果种类相同,如果从 0 开始摘,则只能摘 0 和 1 两个种类 ;

  • 因为当我们在两个果篮都装有水果的情况下,如果再走到下一颗果树,果树的水果种类不是果篮中的任意一种,则停止采摘;
  • 所以就是要找出一块连续的区域,这个连续的区域最多有两种类型的元素,并且在所有找到的符合条件的区域中,找出长度最长的区域;

通过上述例子,我们可以把题目描述最终简化成一个问题模型:

找出长度最长的子数组,子数组中的元素种类<=2


  解法:滑动窗口  

  • 定义 left 指针固定一个起点,然后定义 right 指针向后枚举;
  • 枚举出所有合适的子数组,然后返回所有子数组中长度最长的数组

  • 模拟一个 hash 表 kinds,来统计水果出现的个数;
  • 每 right 遍历一个元素,就把该元素对应的 kinds[ fruits [ i ] ] ++;
  • 然后每次改变 kinds的元素 kinds[ fruits [ i ] ] ,都要判断 kinds 这个数组的有效元素个数是否小于3 ;

如果想不清楚进窗口和出窗口该怎么操作,就回到暴力枚举的基础上,来模拟出进出窗口的操作:

  1. left = 0 ,right = 0;new kinds[ ];
  2. 进窗口(kinds[fruit [ right ] ]++,right++)
  3. 循环判断 3,4,5(kinds.length 是否 >2)
  4. 出窗口(kinds[fruit [ left ] ]--,left++);
  5. 如果因为 kinds[ fruit [ left ] ]--,导致 kinds[fruit [ left ] ] 变成0,则要移除这个元素
  6. 更新结果(不断更新 ret 直到最后拿到最大值)

Map 官方文档


    编写代码: 

 

    分析错误原因: 

  • 因为出窗口这行代码的逻辑,是更新 kinds 中的计数;
  • 如果放到 if 的下面,那么在检查计数为空之前,如果 output 对应的计数原本就是1,那么 if 条件在更新之前就会检查一个过时的值(即1,而不是更新后的0);
  • 意味着,可能 remove 操作不能被正确的执行,所以会报错;
  • 因此,出窗口的操作必须在 if 的前面去更新;

  正确写法  

  方法一:使用容器 Map  

  方法二:用数组模拟哈希表  

根据题目给的上述提示,为了降低执行用时,我们可以通过一个数组模拟哈希表


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


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


 

  1.先快速判断两个字符数相同的字符串是否是“异位词”  

对于这两个字符数相同的字符串,我们如何判断这两个字符串是一个异位词呢?


我们可以先分别对 这两个字符串 的 所有字符 进行排序,然后使用 双指针 依次比对这两个字符串对应的字符即可;

这个方法虽然可以达到目的,但是因为排序操作,使得时间复杂度太高了;

所以,如果是两个字符数相同的字符串,要比较是不是异位词,我们可以统计每一个字符出现的个数即可,因为异位词是不考虑顺序的。

所以我们可以通过哈希表,快速判断两个词是否是异位词:

   暴力解法   

   总结规律   

所以这个枚举的过程,都是从左到右枚举的,所以可以用滑动窗口的解法来解决:

   解法:滑动窗口 + 哈希表   


  • 之前做的关于滑动窗口的题目,窗口大小是不固定的,这题是第二种滑动窗口的题型,就是窗口大小固定(left 和 right 同时移动);
  • 只要定义的两个指针从始至终都是同向移动的,就是滑动窗口的题型;

  1. left = 0 , right = 0;
  2. 定义 hash1 统计 p 字符串中字符的 key,val
  3. 进窗口(定义 hash2,right++,hash2.get(s[ right ])++)
  4. 判断(right - left + 1 > m)(因为窗口大小固定,left 只需要移动一次,所以判断不用写成循环))
  5. 出窗口(hash2.get(s[ right ])--,left++,)
  6. 更新结果 ( check(hash1,hash2) ,返回 true,子串的首元素下标放入返回的 list 中)
  7. 循环 3 4 5 6

   优化 check()    


因为 s 和 p 都是小写字母,所以我们只需要创建一个大小为 26 的数组模拟哈希表即可,数组下标模拟的是哈希表的 key。

那么每次程序执行到调用 check() 的地方,check()中,仅仅需要比较 26 次每个元素的值是否相同即可。


   时间复杂度    

因此,在上述优化后,时间复杂度 O(26*N) —> O(N)


因为我们这道题,哈希表存的是一个一个的字符,所以我们可以用字符数组来模拟哈希表,这时候,比较两个字符数组是非常快的;

但是,如果遇到哈希表存的 key,是一个一个的字符串,就不能再用数组模拟哈希表了


   优化 check() 的判断条件   


我们如果直接调用 check(),来直接比较两个哈希表是否相同 ,是需要比较 26 次才可以出结果的;

如果换难一点的题,可能需要比较更多次,才可以知道两个两个哈希表是否相同,因此我们需要优化 check() 的判断条件;

做法:利用 count 来统计窗口中“有效字符”的个数,一定要注意有效字符的定义

我们要在进窗口的操作过程中,维护 count;

此时,hash1 和 hash2 的 都有一个 c;

  • 所以,在往 hash2 添加了一个字符后,这个字符在 hash1 中也有;
  • 并且这个字符在放入 hash2 后,修改后的个数数字,是小于等于hash1对应字符的个数数字的

满足以上两点,就可以称为是“有效字符”,而 count 就是用来统计这些字符的个数的。

right++,如果遍历到的字符放入 hash2 后,对应的 val 大于 hash1,则说明是无效字符,count不更新

此时,我们需要判断一下,count 是否等于3(p.length),如果 count 刚好等于3(p.length),说明此时,窗口中的字符全是有效字符

所以一边通过进窗口操作更新哈希表,一边可以维护 count;当然,上面说的只是入窗口,出窗口也需要维护 count


思考:此时滑动窗口,right 指向新的字符 a,需要更新 count 吗?

是需要的;但是此时的窗口太大了,需要让 left++,并且从 hash2 中移出出窗口的元素

并且在 left 向后移动的这一步的过程中,第一个 c 变成了多余元素,而第二个 c 变成有效元素;

所以在这一步 left 后挪的过程中,是不改变 count 的值的;

此时的窗口大小等于 p.length,继续向后移动 right,遍历到的字符 e 加到 hash2 中;

每次 right++ 后,需要再次判断窗口的长度,会发现窗口长度大于 p.length,所以又需要调整 left;

在调整 left 之前,我们需要判断此时的  left  是否是一个有效元素

left 指向的元素在 hash2 的 val ,如果小于等于 hash1 中的对应元素的val,则 left 是有效元素;

对于上图的情况,left 向后移动删除的元素是一个有效元素,因此 count--

最后,只需要判断 count 是否与 p.length 相等即可,这样就不需要遍历 26 次了


   总结优化 check() 的判断方法的步骤   

  1. 进窗口:进窗口后,判断 hash2[ input ] <= hash1[ input ]  —> count++
  2. 出窗口:出窗口前,判断  hash2[ input ] <= hash1[ input ] —> count--
  3. 更新结果:只需要判断 count 是否等于 p.length,是则把当前 left 更新到 list 中

   优化后: 

   正确代码: 

   注意:序号一   原因:序号二   


   

 

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

1、使用vscode+eide+stm32cubeMx开发stm32

步骤1&#xff1a;在vscode中安装如下的插件 步骤2&#xff1a;点击Embedded IDE&#xff0c;点击“新建项目”-----空项目-----Cortex-M项目。 步骤3&#xff1a;输入项目名&#xff0c;回车后会要制定保存路径&#xff0c;此时就是一个已项目名命名的文件夹。 步骤4&#xff…

【数据库系列】 Spring Boot 集成 Neo4j 的详细介绍

Spring Boot 提供了对 Neo4j 的良好支持&#xff0c;使得开发者可以更方便地使用图数据库。通过使用 Spring Data Neo4j&#xff0c;开发者可以轻松地进行数据访问、操作以及管理。本文将详细介绍如何在 Spring Boot 应用中集成 Neo4j&#xff0c;包括基本配置、实体定义、数据…

高亚科技签约美妥维志化工,提升业务协同与项目运营效率

近日&#xff0c;中国企业管理软件资深服务商高亚科技与韶关美妥维志化工有限公司&#xff08;以下简称“美妥维志”&#xff09;正式签约。基于高亚科技的8Manage PM项目管理软件&#xff0c;美妥维志将实现项目进度、人员审批及问题的统一管理&#xff0c;提升部门间协同效率…

Python安装(ubuntu)

一&#xff1a;安装指定版本的python python3 --version直接返回ubuntu自带的3.8.10的版本 radarswradarsw-Precision-5560:~$ python3 --version Python 3.8.10通过指令直接安装&#xff0c;会报错如下; radarswradarsw-Precision-5560:~$ sudo apt install python3.11 正在…

大模型基础BERT——Transformers的双向编码器表示

大模型基础BERT——Transformers的双向编码器表示 整体概况 BERT&#xff1a;用于语言理解的深度双向Transform的预训练 论文题目&#xff1a;BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding Bidirectional Encoder Representations from…

云计算复习文档

云计算复习文档 一 云计算概述 名词&#xff1a; 云计算 1.0 &#xff1a; 面向数据中心管理员的IT基础设施资源虚拟化阶段 通过计算虚拟化技术将企业IT应用与底层的基础设施彻底分离、解耦 将多个企业IT应用实例及运行环境复用在相同的物理服务器上&#xff0c;并通过虚…

探索大规模语言模型(LLM)在心理健康护理领域中的应用与潜力

概述 心理健康是公共卫生最重要的领域之一。根据美国国家精神卫生研究所&#xff08;NIMH&#xff09;的数据&#xff0c;到 2021 年&#xff0c;22.8% 的美国成年人将患上某种形式的精神疾病。在全球范围内&#xff0c;精神疾病占非致命性疾病负担的 30%&#xff0c;并被世界…

Tensorflow基本概念

简介&#xff1a;本文从Graph讲到Session&#xff0c;同时讲解了tf.constant创建tensor的用法和variable需要初始化的知识点&#xff0c;可以给你打好一个学习Tensorflow的基础。本文都是基于TensorFlow1.14.0的版本下运行。 本专栏将会系统的讲解TensorFlow在1.14.0版本下的各…

Ubuntu+ROS 机械臂拾取和放置

官方链接&#xff1a;https://github.com/skumra/baxter-pnp 1.下载并安装 SDK 依赖项 sudo apt-get install python-wstool python-rosdep 2.创建新的 catkin 工作区 mkdir -p ~/ros_ws/src cd ~/ros_ws/src 3.使用 wstool 下载 rosinstall 文件并将其复制到 Catkin 工作区…

w~视觉~合集23

我自己的原文哦~ https://blog.51cto.com/whaosoft/12548542 #DragGAN 在 AIGC 的神奇世界里&#xff0c;我们可以在图像上通过「拖曳」的方式&#xff0c;改变并合成自己想要的图像。比如让一头狮子转头并张嘴&#xff1a; 实现这一效果的研究出自华人一作领衔的「Drag You…

从电动汽车到车载充电器:LM317LBDR2G 线性稳压器在汽车中的多场景应用

附上LM317系列选型&#xff1a; LM317BD2TG-TO-263 LM317BTG-TO-220 LM317BD2TR4G-TO-263 LM317D2TG-TO-263 LM317D2TR4G-TO-263 LM317TG-TO-220 LM317LBDR2G-SOP-8 LM317LDR2G-SOP-8 LM317MABDTG-TO-252 LM317MABDTRKG-TO-252 LM317MA…

【已解决】git push一直提示输入用户名及密码、fatal: Could not read from remote repository的问题

问题描述&#xff1a; 在实操中&#xff0c;git push代码到github上一直提示输入用户名及密码&#xff0c;并且跳出的输入框输入用户名和密码后&#xff0c;报错找不到远程仓库 实际解决中&#xff0c;发现我环境有两个问题解决&#xff1a; git push一直提示输入用户名及密码…

测试实项中的偶必现难测bug--互斥逻辑异常

问题: 今天线上出了一个很奇怪的问题,看现象和接口是因为数据问题导致app模块奔溃 初步排查数据恢复后还是出现了数据重复的问题,查看后台实际只有一条数据,但是显示在app却出现了两条一模一样的置顶数据 排查: 1、顺着这个逻辑,我们准备在预发复现这个场景,先是cop…

二五、pxe自动装机

pxe自动装机 pxe------------------------------自动安装系统必要的运行环境 无人值守--------------------为系统定制化的安装需要的软件 pxe的优点&#xff1a; 1、规模化&#xff1a;同时装配多台服务器&#xff08;20-30&#xff09; 2、自动化&#xff1a;系统安装和…

算法魅力-二分查找实战

目录 前言 算法定义 朴素二分模版 二分查找 二分的边界查找 在排序数组中查找元素的第一个和最后一个位置&#xff08;medium&#xff09; 暴力算法 二分查找 边界查找分析 山峰数组的峰顶 暴力枚举 二分查找 搜索旋转排序数组中的最小值&#xff08;medium&#xf…

# 第20章 Cortex-M4-触摸屏

第20章 Cortex-M4-触摸屏 20.1 触摸屏概述 20.1.1 常见的触摸屏分类 电阻式触摸屏、电容式触摸屏、红外式触摸屏、表面声波触摸屏 市场上用的最多的是电阻式触摸屏与电容式触摸屏。红外管式触摸屏多用于投影仪配套设备。 电阻式触摸屏构成&#xff1a;整个屏由均匀电阻构成…

大数据新视界 -- 大数据大厂之 Impala 性能优化:基于数据特征的存储格式选择(上)(19/30)

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

Gitcode文件历史记录查看和还原

文件历史记录 文件历史记录用于记录代码文件的更改历史&#xff0c;它允许用户查看文件的不同版本&#xff0c;了解每个版本的修改内容、作者和提交消息。这对于跟踪文件演进、恢复错误更改、审查代码以及了解项目进展都非常有用。 文件历史记录功能提供了以下核心功能&#…

数据结构-二叉树及其遍历

🚀欢迎来到我的【数据结构】专栏🚀 🙋我是小蜗,一名在职牛马。🐒我的博客主页​​​​​​ ➡️ ➡️ 小蜗向前冲的主页🙏🙏欢迎大家的关注,你们的关注是我创作的最大动力🙏🙏🌍前言 本篇文章咱们聊聊数据结构中的树,准确的说因该是只说一说二叉树以及相…

Java集合(Collection+Map)

Java集合&#xff08;CollectionMap&#xff09; 为什么要使用集合&#xff1f;泛型 <>集合框架单列集合CollectionCollection遍历方式List&#xff1a;有序、可重复、有索引ArrayListLinkedListVector&#xff08;已经淘汰&#xff0c;不会再用&#xff09; Set&#xf…