(day26)leecode热题——找到字符串中所有字母异位词

描述

给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。

异位词 指由相同字母重排列形成的字符串(包括相同的字符串)。

示例 1:

输入: s = "cbaebabacd", p = "abc"
输出: [0,6]
解释:
起始索引等于 0 的子串是 "cba", 它是 "abc" 的异位词。
起始索引等于 6 的子串是 "bac", 它是 "abc" 的异位词。

 示例 2:

输入: s = "abab", p = "ab"
输出: [0,1,2]
解释:
起始索引等于 0 的子串是 "ab", 它是 "ab" 的异位词。
起始索引等于 1 的子串是 "ba", 它是 "ab" 的异位词。
起始索引等于 2 的子串是 "ab", 它是 "ab" 的异位词。

提示:

  • 1 <= s.length, p.length <= 3 * 104
  • s 和 p 仅包含小写字母

超时代码

class Solution:def findAnagrams(self, s: str, p: str) -> List[int]:li = [s[i:i+len(p)] for i in range(0, len(s)-len(p)+1, 1)]lis = []for i in range(len(li)):if sorted(li[i]) == sorted(p):lis.append(i)else:continuereturn lis

 leecode题解labuladong

 

from collections import Counter, defaultdict
class Solution:def findAnagrams(self, s: str, p: str) -> List[int]:need = Counter(p)  # 统计目标字符串t中每个字符的频率window = defaultdict(int)  # 记录窗口中字符的频率left, right = 0, 0  # 左右指针初始化valid = 0  # 记录当前窗口中满足条件的字符数res = []  # 存储结果的列表while right < len(s):  # 遍历字符串sc = s[right]  # 当前字符right += 1  # 移动右指针# 进行窗口内数据的一系列更新if c in need:window[c] += 1if window[c] == need[c]:valid += 1# 判断左侧窗口是否需要收缩while right - left >= len(p):# 当窗口符合条件时,把起始索引加入resif valid == len(need):res.append(left)d = s[left]  # 要移出窗口的字符left += 1  # 移动左指针# 进行窗口内数据的一系列更新if d in need:if window[d] == need[d]:valid -= 1window[d] -= 1return res

 整体分析

1. 初始化阶段
  • 统计目标字符串 t 中每个字符的频率: 使用 Counter 创建字典 need,记录 t 中每个字符的频率。

  • 初始化窗口字典: 使用 defaultdict(int) 创建字典 window,用于记录当前窗口中字符的频率。

  • 设置左右指针: 初始化左右指针 leftright 均为0。

  • 初始化辅助变量: 变量 valid 用于记录当前窗口中满足条件的字符数。 列表 res 用于存储结果,即符合条件的起始索引。

2. 扩展右边界
  • 遍历字符串 s: 使用 while 循环遍历字符串 s,右指针 right 从左到右移动。

  • 更新窗口字符频率: 将 right 指针指向的字符加入窗口,更新 window 字典中该字符的频率。

  • 检查是否满足条件: 如果该字符在 need 字典中,并且其频率与 need 中的频率一致,则更新 valid 计数。

3. 收缩左边界
  • 判断窗口大小: 当窗口的大小达到字符串 t 的长度时,进入内层 while 循环。

  • 检查窗口是否符合条件: 如果当前窗口中的字符频率与 t 中字符频率一致,则将 left 指针的位置加入结果列表 res

  • 收缩窗口: 移动 left 指针,缩小窗口,并更新窗口中左边字符的频率。

  • 更新满足条件的字符数: 如果移除的字符在 need 字典中,并且其频率在窗口中不再满足 need 的要求,则更新 valid 计数。

4. 返回结果
  • 输出结果列表: 当所有字符遍历完成后,返回结果列表 res,其中存储了所有符合条件的起始索引。
关键点
  • 滑动窗口:通过左右指针维护一个大小为 t 长度的窗口。
  • 频率统计:使用 Counterdefaultdict 统计字符频率。
  • 条件判断:通过 valid 判断当前窗口是否符合条件。
  • 结果存储:符合条件时,将窗口的起始索引存储到结果列表中。

 

 滑动窗口

 维护一个窗口,不断滑动,然后更新答案。算法技巧的时间复杂度是 O(N),比字符串暴力算法要高效得多。细节:如何向窗口中添加新元素,如何缩小窗口,在窗口滑动的哪个阶段更新结果。

python框架

from collections import defaultdictdef sliding_window(s, t):# 创建need字典,记录目标字符串t中每个字符的频率need = defaultdict(int)for c in t:need[c] += 1window = defaultdict(int)  # 创建window字典,记录当前窗口中每个字符的频率left, right = 0, 0  # 初始化左、右指针valid = 0  # 记录当前窗口中满足条件的字符数while right < len(s):# c 是将移入窗口的字符c = s[right]# 右移窗口right += 1# 进行窗口内数据的一系列更新# 此处应填写窗口右移时的处理逻辑...# debug 输出的位置print(f"window: [{left}, {right})")# 判断左侧窗口是否要收缩while window_needs_shrink():  # 此处应填写判断窗口是否需要收缩的条件# d 是将移出窗口的字符d = s[left]# 左移窗口left += 1# 进行窗口内数据的一系列更新# 此处应填写窗口左移时的处理逻辑...def window_needs_shrink():# 这是一个占位函数,用于判断窗口是否需要收缩# 你需要根据具体逻辑实现该函数return False

其中两处 ... 表示的更新窗口数据的地方,到时候你直接往里面填就行了。

而且,这两个 ... 处的操作分别是右移和左移窗口更新操作,等会你会发现它们操作是完全对称的。

 框架说明

上述Python框架代码主要涉及以下几个重要的知识点和数据结构:

 1. defaultdict
from collections import defaultdict

- **定义**:`defaultdict` 是 `collections` 模块中的一个类,它继承自内置的 `dict` 类。与普通字典不同的是,`defaultdict` 在访问不存在的键时,不会抛出 `KeyError`,而是会根据提供的默认工厂函数生成一个默认值。
- **用途**:在需要频繁处理不存在的键的情况下,`defaultdict` 可以简化代码,避免手动检查键是否存在。
 

need = defaultdict(int)
for c in t:need[c] += 1


在这里,`need` 是一个 `defaultdict`,默认值为 `int` 类型,即默认值为 0。这样,在统计字符频率时,如果某个字符在 `need` 中不存在,会自动添加并初始化为 0。

2. 滑动窗口

滑动窗口是一种常用于字符串或数组问题的算法技巧,用于在一维数据结构中维护一个动态范围(窗口)并根据特定条件进行调整。

- **用途**:适用于需要在一维数据结构(如字符串或数组)中查找满足特定条件的子数组或子字符串的问题。
- **核心思想**:通过两个指针(左指针 `left` 和右指针 `right`)维护一个窗口,动态调整窗口大小,移动窗口的位置以找到符合条件的子数组或子字符串。
- **示例**:

left, right = 0, 0
while right < len(s):c = s[right]right += 1...while window_needs_shrink():d = s[left]left += 1...
3. 字符频率统计

使用字典或 `defaultdict` 统计字符串中字符的频率,是处理字符串问题的常用技巧。

- **用途**:在涉及字符串比较、匹配等操作时,字符频率统计是一个基础步骤。
- **示例**:

need = defaultdict(int)
for c in t:need[c] += 1


在这里,`need` 字典用于统计字符串 `t` 中每个字符的频率。

4. 占位符函数
 
def window_needs_shrink():return False

- **用途**:在初步搭建框架时,占位符函数用于表示某个需要实现的具体逻辑。
- **实现**:在实际应用中,这个函数需要根据特定问题的需求进行实现,以判断窗口是否需要收缩。

 5. 字符串操作

在字符串中,通过索引访问字符是常见的操作。

- **示例**:

c = s[right]  # 获取当前右指针指向的字符
d = s[left]   # 获取当前左指针指向的字符


通过这种方式,可以获取窗口左右边界的字符,进行相应的逻辑处理。

总结

上述代码框架结合了 `defaultdict`、滑动窗口、字符频率统计等数据结构和算法技巧,为解决类似字符串匹配或子数组查找的问题提供了基础结构。通过填充具体的逻辑,可以实现特定功能的滑动窗口算法。

 速记口诀

 

整体思路 

滑动窗口算法的思路是这样:

1、我们在字符串 S 中使用双指针中的左右指针技巧,初始化 left = right = 0,把索引左闭右开区间 [left, right) 称为一个「窗口」。

2、我们先不断地增加 right 指针扩大窗口 [left, right),直到窗口中的字符串符合要求(包含了 T 中的所有字符)。

3、此时,我们停止增加 right,转而不断增加 left 指针缩小窗口 [left, right),直到窗口中的字符串不再符合要求(不包含 T 中的所有字符了)。同时,每次增加 left,我们都要更新一轮结果。

4、重复第 2 和第 3 步,直到 right 到达字符串 S 的尽头。

这个思路其实也不难,**第 2 步相当于在寻找一个「可行解」,然后第 3 步在优化这个「可行解」,最终找到最优解,**也就是最短的覆盖子串。左右指针轮流前进,窗口大小增增减减,窗口不断向右滑动,这就是「滑动窗口」这个名字的来历。

下面画图理解一下,needs 和 window 相当于计数器,分别记录 T 中字符出现次数和「窗口」中的相应字符的出现次数。

初始状态:

 

{:align=center}

增加 right,直到窗口 [left, right) 包含了 T 中所有字符:

 

{:align=center}

现在开始增加 left,缩小窗口 [left, right)。

 

{:align=center}

直到窗口中的字符串不再符合要求,left 不再继续移动。

 

{:align=center}

之后重复上述过程,先移动 right,再移动 left…… 直到 right 指针到达字符串 S 的末端,算法结束。

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

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

相关文章

【Git-驯化】一文搞懂git中代码冲突的解决方案大全

【Git-驯化】一文搞懂git中代码冲突的解决方案大全 本次修炼方法请往下查看 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我工作、学习、实践 IT领域、真诚分享 踩坑集合&#xff0c;智慧小天地&#xff01; &#x1f387; 免费获取相关内容文档关注&#xff1a…

[C++实战]日期类的实现

&#x1f496;&#x1f496;&#x1f496;欢迎来到我的博客&#xff0c;我是anmory&#x1f496;&#x1f496;&#x1f496; 又和大家见面了 欢迎来到C探索系列 作为一个程序员你不能不掌握的知识 先来自我推荐一波 个人网站欢迎访问以及捐款 推荐阅读 如何低成本搭建个人网站…

ELK安装(Elasticsearch+Logstash+Kibana+Filebeat)

一、简介 1.1、软件简介 ELK其实是Elasticsearch&#xff0c;Logstash 和 Kibana三个产品的首字母缩写&#xff0c;这三款都是开源产品。 1.1.1、Elasticsearch简介 Elasticsearch 是一个分布式、高扩展、高实时的搜索与数据分析引擎。它能很方便的使大量数据具有搜索、分析…

springboot微信老人健康与饮食管理系统-计算机毕业设计源码82939

基于微信老人健康与饮食管理系统的小程序 摘 要 基于Spring Boot的微信老人健康与饮食管理系统的小程序致力于为老年人提供便捷的健康管理和饮食指导服务。该小程序整合了健康资讯浏览、食谱推荐、健康评估等功能模块&#xff0c;通过系统的设计与实现&#xff0c;旨在帮助老年…

古丝绸之路传闻二:十年败壳精灵显,一介穷神富贵来

古丝绸之路传闻二&#xff1a;十年败壳精灵显&#xff0c;一介穷神富贵来 &#xff08;接上节&#xff1a;古丝绸之路传闻&#xff1a;分内功名匣里财&#xff0c;不关聪慧不关呆&#xff09; 先别说闲话。且说众人带着经纪主人到船上发货&#xff0c;文若虚把之前的事情说了一…

AccessLog| 一款开源的日志分析系统

前言 ClkLog作为分析系列产品中的前端数据分析系统&#xff0c;通过采集前端应用数据进行用户行为分析。其社区版从23年9月发布至今已有近一年&#xff0c;商业版也上线快半年&#xff0c;感谢大家一直以来的关注和支持&#xff0c;ClkLog会继续做好产品升级与服务&#xff0c;…

Linux冯诺依曼体系、操作系统、进程概念、进程状态、进程切换

个人主页&#xff1a;仍有未知等待探索-CSDN博客 专题分栏&#xff1a;Linux 目录 一、冯诺依曼体系结构 二、操作系统 1、概念 2、为什么要有操作系统&#xff1f; 3、理解操作系统 1.管理的本质 2.管理的概念 3.操作系统结构图 4.为什么要有操作系统&#xff1f; 三…

python-NLP:2词性标注与命名实体识别

文章目录 词性标注命名实体识别时间命名实体&#xff08;规则方法&#xff09;CRF 命名实体识别方法 词性标注 词性是词汇基本的语法属性&#xff0c;通常也称为词类。词性标注是在给定句子中判定每个词的语法范畴&#xff0c;确定其词性并加以标注的过程。例如&#xff0c;表示…

Python机器学习实战:分类算法之逻辑回归-泰坦尼克号乘客生还预测

为了解决特定问题而进行的学习是提高效率的最佳途径。这种方法能够使我们专注于最相关的知识和技能&#xff0c;从而更快地掌握解决问题所需的能力。 目录 逻辑回归算法介绍 练习题 Python代码与分析 1、读入数据&#xff0c;观察数据情况 2、各属性与生还情况的关联 3、…

用Python做一个翻译软件,比上浏览器快100倍

简单的用Python来做一个翻译软件 开发环境 Python 3.10 Pycharm模块使用 requests -> pip install requests hashlib tkinter案例分为三部分: 1. 爬虫: 获取翻译接口, 请求获取翻译结果问题1: 接口抓包分析问题2: 请求需要写cookie问题3: 不同文本翻译, s加密参数2. 界面…

PDF解锁网站

https://smallpdf.com/cn/unlock-pdfhttps://smallpdf.com/cn/unlock-pdfhttps://www.freemypdf.comhttps://www.freemypdf.com

【python】python图书管理系统_普通用户+管理员菜单(源码+论文)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

[代码审计]记一次简单的java代码审计

如果觉得该文章有帮助的&#xff0c;麻烦师傅们可以搜索下微信公众号&#xff1a;良月安全。点个关注&#xff0c;感谢师傅们的支持。 免责声明 本博客所发布的所有内容&#xff0c;包括但不限于信息、工具、项目以及文章&#xff0c;均旨在提供学习与研究之用。所有工具安全…

FastAPI(七十六)实战开发《在线课程学习系统》接口开发-- 课程详情

源码见&#xff1a;"fastapi_study_road-learning_system_online_courses: fastapi框架实战之--在线课程学习系统" 这个接口用户可以不登录&#xff0c;因为我们的课程随意浏览 那么我们梳理下这里的逻辑 1.根据课程id判断课程是否存在 2.课程需要返回课程的详情 3…

C# Task.WaitAll 的用法

目录 简介 1.WaitAll(Task[], Int32, CancellationToken) 2.WaitAll(Task[]) 3.WaitAll(Task[], Int32) 4.WaitAll(Task[], CancellationToken) 5.WaitAll(Task[], TimeSpan) 结束 简介 Task.WaitAll 是 C# 中用于并行编程的一个的方法&#xff0c;它属于 System.Threa…

DjangoRF-5-用户管理-users接口

1、创建模型&#xff0c;user模型之前创建过了&#xff0c;继承了原有的模型类 2、序列化器 在 users/serializers.py 模块中添加&#xff1a; class UserSerializer(serializers.ModelSerializer):class Meta:model Userfields [id, username, password, mobile, email, is…

【简单讲解Perl语言】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

基于微信小程序+SpringBoot+Vue的核酸检测服务系统(带1w+文档)

基于微信小程序SpringBootVue的核酸检测服务系统(带1w文档) 基于微信小程序SpringBootVue的核酸检测服务系统(带1w文档) 在目前的情况下&#xff0c;可以引进一款医院核酸检测服务系统这样的现代化管理工具&#xff0c;这个工具就是解决上述问题的最好的解决方案。它不仅可以实…

20240727生活沉思------------关于报考软考高级架构师

软考高级架构师 软考高级架构师 缴费 主要是报的千峰 1880元。 相对来说还算可以吧。。。其他也没给我机会选择啊 备考 我现在开始备考&#xff0c;考试时间2024年11月。 今天是正式开始7.27号。 给大家看看接下来我的课程安排&#xff1a; 额&#xff0c;还是满满当当的…

日入800+小红书AI表情包项目拆解

一个高考结束之后&#xff0c;进入暑假&#xff0c;只要有手就能做的AI搞钱项目&#xff0c;不到2个月的时间在小某书上成功涨粉5w&#xff0c;通过发布广告&#xff0c;一条广告甚至还能赚到2000元&#xff1b; 只要有市场需求就可以制作这种表情包快速搞钱&#xff0c;上手非…