当前位置: 首页 > news >正文

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

   

 


  水果成篮  


水果成篮


 

  题目描述  

因为只有两个篮子,每个篮子装的水果种类相同,如果从 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 中

   优化后: 

   正确代码: 

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


   

 

相关文章:

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

水果成篮 水果成篮 题目描述 因为只有两个篮子&#xff0c;每个篮子装的水果种类相同&#xff0c;如果从 0 开始摘&#xff0c;则只能摘 0 和 1 两个种类 &#xff1b; 因为当我们在两个果篮都装有水果的情况下&#xff0c;如果再走到下一颗果树&#xff0c;果树的水果种类…...

Go 数据库查询与结构体映射

下面是关于如何使用 Go 进行数据库查询并映射数据到结构体的教程&#xff0c;重点讲解 结构体字段导出 和 db 标签 的使用。 Go 数据库查询与结构体映射教程 在 Go 中&#xff0c;我们可以使用 database/sql 或 sqlx 等库与数据库进行交互。为了方便地将数据库查询结果映射到结…...

Wi-Fi背后的工作原理与技术发展历程介绍【无线通信小百科】

1个视频说清楚WIFI&#xff1a;频段/历程/技术参数/常用模块 智能手机拥有率越来越高的今天&#xff0c;大家已经习惯了通过无线网络上网的方式。除了在外面需要用手机流量&#xff0c;我们通常在家里或者机场&#xff0c;商场都可以通过Wi-Fi连接上网。本期文章将为大家介绍Wi…...

2024 年(第 7 届)“泰迪杯”数据分析技能赛B 题 特殊医学用途配方食品数据分析 完整代码 结果 可视化分享

一、背景特殊医学用途配方食品简称特医食品&#xff0c;是指为满足进食受限、消化吸收障碍、代谢素乱或者特定疾病状态人群对营养素或者膳食的特殊需要&#xff0c;专门加工配置而成的配方食品&#xff0c;包括0月龄至12月龄的特殊医学用途婴儿配方食品和适用于1岁以上的特殊医…...

STM32学习笔记------编程驱动蜂鸣器实现音乐播放

1. 硬件准备 STM32开发板&#xff1a;STM32F407系列蜂鸣器&#xff1a;常见的蜂鸣器分为两类&#xff1a;有源蜂鸣器和无源蜂鸣器。若使用有源蜂鸣器&#xff0c;只需提供电源和控制信号即可&#xff1b;若使用无源蜂鸣器&#xff0c;则需要控制频率。外接电源&#xff08;可选…...

ubuntu18.04 安装与卸载NCCL conda环境安装PaddlePaddle

cuda版本11.2 说明PaddlePaddle需要安装NCCL 1、Log in | NVIDIA Developer 登录官网 找到对应版本 官方提供了多种安装方式&#xff0c;本文使用Local installers (x86)本地安装 点击对应的版本下载如&#xff1a; nccl-local-repo-ubuntu1804-2.8.4-cuda11.2_1.0-1_amd6…...

AI有鼻子了,还能远程传输气味,图像生成香水

众所周知&#xff0c;图像、音乐能用AI生成&#xff0c;但出乎意料的是&#xff0c;气味也行。最近&#xff0c;一个名叫Osmo的初创公司宣布&#xff0c;他们成功地将气味数字化了。第一个成功的案例是“新鲜的夏季李子”&#xff0c;而且复现出的味道“闻起来”很不错。整个过…...

学习配置dify过程记录

最近在学习安装 Dify 并集成 Ollama 和 Xinference&#xff0c;学习过程中遇到很多问题&#xff0c;所以我都记录下来。 本人电脑环境&#xff1a;MacBook Pro 15.1系统 基本是基于B站教程一步步搭建: 【Dify快速入门 | 本地部署Dify基于Llama 3.1和OpenAI创建聊天机器人与知…...

简易抽奖器源码以及打包操作

import wx import random import time# 定义Myframe类,继承Frame class Myframe(wx.Frame):# 奖品rewards [桥本香奈, 二代CC, NaNa, 情深叉]# 构造方法def __init__(self):# 父类初始化super().__init__(None, title主界面, size(500, 400), pos(500, 200))# 创建面板&#x…...

一文了解什么是腾讯云开发

一文了解什么是腾讯云开发 关于云开发的猜想腾讯云开发腾讯云开发的优势无服务跨平台轻松托管节约成本 快速上手云开发环境快速搭建管理后台 云开发体验 关于云开发的猜想 说到云开发&#xff0c;作为开发者的大家是否大概就有了想法。比如说过去的开发工作都是在自己本地电脑…...

[CKS] K8S NetworkPolicy Set Up

最近准备花一周的时间准备CKS考试&#xff0c;在准备考试中发现有一个题目关于不安全项目修复的题目。 ​ 专栏其他文章: [CKS] Create/Read/Mount a Secret in K8S-CSDN博客[CKS] Audit Log Policy-CSDN博客 -[CKS] 利用falco进行容器日志捕捉和安全监控-CSDN博客[CKS] K8S Ne…...

【JAVA】Java基础—面向对象编程:构造方法-实现一个Car类,包含多个构造方法,创建不同的汽车对象

在Java中&#xff0c;构造方法则是用于创建对象的特殊方法。通过构造方法&#xff0c;可以在创建对象时初始化其属性。构造方法的重载允许我们根据不同的需求定义多个构造方法&#xff0c;从而灵活地创建对象。 我们可以将汽车的构造方法比作汽车的配置选项。比如&#xff0c;…...

初识网络编程TCP/IP

目录 前言相关名词解释应用层协议——HTTP传输层协议socketTCP帧头格式三次握手、四次挥手 UDPTCP的socket实现 参考博文 前言 刚碰到网络编程&#xff0c;会出现一堆协议、概念、这层次那技术的&#xff0c;头都大了&#xff0c;还是得总结总结…… 相关名词解释 ✨✨网络…...

快速入门Zookeeper

Zookeeper ZooKeeper作为一个强大的开源分布式协调服务&#xff0c;扮演着分布式系统中至关重要的角色。它提供了一个中心化的服务&#xff0c;用于维护配置信息、命名、提供分布式同步以及提供组服务等。通过其高性能和可靠的特性&#xff0c;ZooKeeper能够确保在复杂的分布式…...

Filter and Search 筛选和搜索

Goto Data Grid 数据网格 Filter and Search 筛选和搜索 Filter Drop-down Menus (Excel-style) 筛选器下拉菜单&#xff08;Excel 样式&#xff09; 要调用列的筛选器下拉菜单&#xff0c;请单击列标题中的筛选器图标。在 “Values” 选项卡中&#xff0c;用户可以从 Data …...

spark的学习-06

SparkSQL读写数据的方式 1&#xff09;输入Source 方式一&#xff1a;给定读取数据源的类型和地址 spark.read.format("json").load(path) spark.read.format("csv").load(path) spark.read.format("parquet").load(path) 方式二&#xff1a…...

Linux C/C++ Socket 编程

本文目录 Linux C语言 socket 编程 client 端头文件 unistd.h & arpa/inet.h1. **unistd.h**2. **arpa/inet.h** socket() 创建套接字sockaddr_in 结构体inet_pton()connect()send()recv()send() 和 recv() 中的 flags 参数**默认行为&#xff08;flags 0&#xff09;的特…...

Flutter错误: uses-sdk:minSdkVersion 16 cannot be smaller than version 21 declared

前言 今天要做蓝牙通信的功能&#xff0c;我使用了flutter_reactive_ble这个库&#xff0c;但是在运行的时候发现一下错误 Launching lib/main.dart on AQM AL10 in debug mode... /Users/macbook/Desktop/test/flutter/my_app/android/app/src/debug/AndroidManifest.xml Err…...

Spark 的容错机制:保障数据处理的稳定性与高效性

Spark 的介绍与搭建&#xff1a;从理论到实践_spark环境搭建-CSDN博客 Spark 的Standalone集群环境安装与测试-CSDN博客 PySpark 本地开发环境搭建与实践-CSDN博客 Spark 程序开发与提交&#xff1a;本地与集群模式全解析-CSDN博客 Spark on YARN&#xff1a;Spark集群模式…...

TCP可靠连接的建立和释放,TCP报文段的格式,UDP简单介绍

TCP连接的建立&#xff08;三次握手&#xff09; 建立连接使用的三报文 SYN 报文仅用于 TCP 三次握手中的第一个和第二个报文&#xff08;SYN 和 SYN-ACK&#xff09;&#xff0c;用于初始化连接的序列号。数据传输阶段不再使用 SYN 标志。 SYN 报文通常只携带连接请求信息&a…...

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…...

生成xcframework

打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式&#xff0c;可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...

stm32G473的flash模式是单bank还是双bank?

今天突然有人stm32G473的flash模式是单bank还是双bank&#xff1f;由于时间太久&#xff0c;我真忘记了。搜搜发现&#xff0c;还真有人和我一样。见下面的链接&#xff1a;https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...

从零实现富文本编辑器#5-编辑器选区模型的状态结构表达

先前我们总结了浏览器选区模型的交互策略&#xff0c;并且实现了基本的选区操作&#xff0c;还调研了自绘选区的实现。那么相对的&#xff0c;我们还需要设计编辑器的选区表达&#xff0c;也可以称为模型选区。编辑器中应用变更时的操作范围&#xff0c;就是以模型选区为基准来…...

边缘计算医疗风险自查APP开发方案

核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...

uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖

在前面的练习中&#xff0c;每个页面需要使用ref&#xff0c;onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入&#xff0c;需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析

这门怎么题库答案不全啊日 来简单学一下子来 一、选择题&#xff08;可多选&#xff09; 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘&#xff1a;专注于发现数据中…...

2.Vue编写一个app

1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...

Spring AI与Spring Modulith核心技术解析

Spring AI核心架构解析 Spring AI&#xff08;https://spring.io/projects/spring-ai&#xff09;作为Spring生态中的AI集成框架&#xff0c;其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似&#xff0c;但特别为多语…...

关键领域软件测试的突围之路:如何破解安全与效率的平衡难题

在数字化浪潮席卷全球的今天&#xff0c;软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件&#xff0c;这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下&#xff0c;实现高效测试与快速迭代&#xff1f;这一命题正考验着…...