Python算法题集_找到字符串中所有字母异位词

本文为Python算法题集之一的代码示例

题目438:找到字符串中所有字母异位词

说明:给定两个字符串 sp,找到 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

  • sp 仅包含小写字母


问题分析

  1. 因p是固定的,所以检查是否为p的异位词可以直接使用数组的字符计数比较即可【p仅含小写字母,因此数组只有26个元素】
  2. 因p长度固定,因此单循环即可遍历字符串
  3. 优化思路
    1. 减少计算
    2. 加快比较

  1. 标准版【循环进行异位词比较】,性能良好,超越89%,标准版的性能就比较高,说明本题可以优化的空间不大

    注意:CheckFuncPerf是我手搓的函数用时和内存占用模块,下载地址在这里:测量函数运行用时、内存占用的代码单元CheckFuncPerf.py以及使用方法
    在这里插入图片描述

    import CheckFuncPerf as cfp
    
    def findAnagrams(s: str, p: str) -> list[int]:
        list_p = [0] * 26
        list_s = [0] * 26
        list_result = []
        for iIdx in range(len(p)):
            list_p[ord(p[iIdx])-ord('a')] += 1
        for iIdx in range(len(s)):
            list_s[ord(s[iIdx])-ord('a')] += 1
            if iIdx < len(p) - 1:
                continue
            if list_s == list_p:
                list_result.append(iIdx - len(p) + 1)
            list_s[ord(s[iIdx-len(p)+1]) - ord('a')] -= 1
        return list_result
    
    s, p = 'cbaebabacd', 'abc'
    result = cfp.getTimeMemoryStr(findAnagrams, s, p)
    print(result['msg'],'执行结果={}'.format(result['result']))
    # 运行结果
    函数 findAnagrams 的运行时间为 0.00 ms;内存使用量为 4.00 KB 执行结果=[0, 6]
    
  2. 优化版【每次判断是否出现未出现在p中的字符,如出现进行跳跃】,性能自由落体,超越42%
    在这里插入图片描述

    这种优化有赖于p的特性,p的长度越长,优化效果越好;反之,因为每个字符都要多一次比较,性能反而会下降

    def findAnagrams_ext1(s: str, p: str) -> list[int]:
        list_p = [0] * 26
        list_s = [0] * 26
        list_result = []
        for iIdx in range(len(p)):
            list_p[ord(p[iIdx])-ord('a')] += 1
        iIdx, ileft = 0, 0
        while iIdx < len(s):
            if p.find(s[iIdx])<0:
                if iIdx<len(p):
                    for jIdx in range(iIdx):
                        list_s[ord(s[jIdx])-ord('a')] = 0
                else:
                    for jIdx in range(len(p)):
                        list_s[ord(s[iIdx-jIdx])-ord('a')] = 0
                iIdx += 1
                ileft = iIdx
                continue
            list_s[ord(s[iIdx])-ord('a')] += 1
            if iIdx < len(p) + ileft - 1:
                iIdx += 1
                continue
            if list_s == list_p:
                list_result.append(iIdx - len(p) + 1)
            list_s[ord(s[iIdx-len(p)+1]) - ord('a')] -= 1
            ileft += 1
            iIdx += 1
        return list_result
        
    s, p = 'cbaebabacd', 'abc'
    result = cfp.getTimeMemoryStr(findAnagrams_ext1, s, p)
    print(result['msg'],'执行结果={}'.format(result['result']))
    # 运行结果
    函数 findAnagrams_ext1 的运行时间为 0.00 ms;内存使用量为 0.00 KB 执行结果=[0, 6]
    
  3. 计算优化版【标准版中,将ord('a')先计算出来,避免每次计算】,性能优异,超越97%
    在这里插入图片描述

    def findAnagrams_iorda(s: str, p: str) -> list[int]:
        iOrda = ord('a')
        list_p = [0] * 26
        list_s = [0] * 26
        list_result = []
        for iIdx in range(len(p)):
            list_p[ord(p[iIdx])-iOrda] += 1
        for iIdx in range(len(s)):
            list_s[ord(s[iIdx])-iOrda] += 1
            if iIdx < len(p) - 1:
                continue
            if list_s == list_p:
                list_result.append(iIdx - len(p) + 1)
            list_s[ord(s[iIdx-len(p)+1]) - iOrda] -= 1
        return list_result
        
    s, p = 'cbaebabacd', 'abc'
    result = cfp.getTimeMemoryStr(findAnagrams_iorda, s, p)
    print(result['msg'],'执行结果={}'.format(result['result']))
    # 运行结果
    函数 findAnagrams_iorda 的运行时间为 0.00 ms;内存使用量为 0.00 KB 执行结果=[0, 6]
    
  4. 优化加强版【优化版中,将ord('a')先计算出来,避免每次计算】,性能一般,超越54%
    在这里插入图片描述

    def findAnagrams_ext1_iorda(s: str, p: str) -> list[int]:
        iOrda = ord('a')
        list_p = [0] * 26
        list_s = [0] * 26
        list_result = []
        for iIdx in range(len(p)):
            list_p[ord(p[iIdx])-iOrda] += 1
        iIdx, ileft = 0, 0
        while iIdx < len(s):
            if p.find(s[iIdx])<0:
                if iIdx<len(p):
                    for jIdx in range(iIdx):
                        list_s[ord(s[jIdx])-iOrda] = 0
                else:
                    for jIdx in range(len(p)):
                        list_s[ord(s[iIdx-jIdx])-iOrda] = 0
                iIdx += 1
                ileft = iIdx
                continue
            list_s[ord(s[iIdx])-iOrda] += 1
            if iIdx < len(p) + ileft - 1:
                iIdx += 1
                continue
            if list_s == list_p:
                list_result.append(iIdx - len(p) + 1)
            list_s[ord(s[iIdx-len(p)+1]) - iOrda] -= 1
            ileft += 1
            iIdx += 1
        return list_result
        
    s, p = 'cbaebabacd', 'abc'
    result = cfp.getTimeMemoryStr(findAnagrams_ext1_iorda, s, p)
    print(result['msg'],'执行结果={}'.format(result['result']))
    # 运行结果
    函数 findAnagrams_ext1_iorda 的运行时间为 0.00 ms;内存使用量为 0.00 KB 执行结果=[0, 6]
    

    一日练,一日功,一日不练十日空

    may the odds be ever in your favor ~

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

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

相关文章

【c++】高精度算法(洛谷刷题2024)玩具谜题详解(含图解)

系列文章目录 第三题&#xff1a;玩具谜题 视频讲解&#xff1a;http://【洛谷题单 - 算法 - 高精度】https://www.bilibili.com/video/BV1Ym4y1s7BD?vd_source66a11ab493493f42b08b31246a932bbb 文章目录 目录 系列文章目录 文章目录 前言 一、题目分析以及思考 二、代码…

查询redis路径,清除redis缓存

查询redis路径 1、执行ps -ef | grep redis 命令&#xff0c;结果如下&#xff08;记住PID&#xff09; 2、执行ps -u 系统用户名&#xff0c;进一步确定进程id, 我这里的系统用户名是root&#xff0c;执行ps -u root&#xff0c;结果如下&#xff1a; 结合1的操作结果图可知…

SERVLET生命周期API

SERVLET生命周期API 在servlet的生命周期中,将发生创建Servlet上下文、创建会话、向Servlet上下文添加属性等各种事件。在servlet的生命周期内发生事件时,Web容器将通知侦听器类。要接收事件的通知,侦听器类需要扩展Servlet API的侦听器接口。 1. 事件类型 servlet生命周期…

关于如何利用ChatGPT提高编程效率的

自从去年ChatGPT3.5推出以后&#xff0c;这一年时间在编程过程中我也在慢慢熟悉人工智能的使用&#xff0c;目前来看即使是免费的ChatGPT3.5对于编程效率的提升也是有很大帮助的&#xff0c;虽然在使用过程中确实出现了一些问题&#xff0c;本文记录下我的一些心得体会和用法。…

Peter算法小课堂—二叉堆(优先队列)

课前小视频&#xff1a;(7 封私信 / 62 条消息) 看动画&#xff0c;学算法&#xff0c;C实现建立二叉堆&#xff0c;优先队列和堆排序的基础 - 知乎 (zhihu.com) 二叉堆&#xff08;优先队列&#xff09; 大家想想&#xff0c;什么数据结构能做到插入&#xff08;删除&#x…

IDEA 构建开发环境

本博客主要讲解了如何创建一个Maven构建Java项目。&#xff08;本文是创建一个用Maven构建项目的方式&#xff0c;所以需要对Maven有一定的了解&#xff09; IDEA 构建开发环境 一、创建一个空工程二、构建一个普通的Maven模块 一、创建一个空工程 创建一个空的工程 * 设置整…

声音模拟训练

环境配置 参考文章&#xff1a; https://github.com/SUC-DriverOld/so-vits-svc-Chinese-Detaild-Documents 1:打开CMD nvidia-smi.exe 查询显卡 cuda VERSION:12.3 2:打开https://pytorch.org/get-started 我的系统是12.3 3&#xff1a;使用google 搜索 nvidia develope…

哈希概念 | 哈希函数 | 哈希冲突 | 哈希桶实现 | 哈希线性探测代码实现 | 闭散列 | 开散列 | 字符串哈希算法

文章目录 1.哈希概念2.哈希冲突3.解决哈希冲突3.1.闭散列3.2.开散列 4.字符串哈希算法 1.哈希概念 顺序结构以及平衡树中&#xff0c;元素关键码与其存储位置之间没有对应的关系&#xff0c;因此在查找一个元素时&#xff0c;必须要经过关键码的多次比较。如果一个顺序结构&am…

80.网游逆向分析与插件开发-背包的获取-自动化助手显示物品数据1

内容参考于&#xff1a;易道云信息技术研究院VIP课 上一个内容&#xff1a;升级Notice类获得背包基址-CSDN博客 码云地址&#xff08;ui显示角色数据 分支&#xff09;&#xff1a;https://gitee.com/dye_your_fingers/sro_-ex.git 码云版本号&#xff1a;3be017de38c50653b…

BGP:04 fake-as

使用 fake-as 可以将本地真实的 AS 编号隐藏&#xff0c;其他 AS 内的对等体在指定本端对等体所在的AS 编号时&#xff0c;应该设置成这个伪AS 编号。 这是实验拓扑&#xff0c;IBGP EBGP 邻居都使用物理接口来建立 基本配置&#xff1a; R1: sys sysname R1 int loo0 ip add…

面了快手电商数据分析师岗(实习),被问的汗流浃背。。。。

最近技术群的一位同学&#xff0c;分享了他面试快手数据分析师岗(实习)的经验。我看了一下面试题&#xff0c;说实话内容不难&#xff0c;他直言没有认真准备。 今天整理后分享给大家&#xff0c;如果你对这块面试感兴趣&#xff0c;可以文末加入我们的面试、技术群 内容 1&…

时序预测 | Python基于Multihead-Attention-TCN-LSTM的时间序列预测

目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 时序预测 | Python基于Multihead-Attention-TCN-LSTM的时间序列预测 Multihead-Attention-TCN-LSTM&#xff08;多头注意力-TCN-LSTM&#xff09;是一种结合了多个注意力机制、时序卷积网络&#xff08;TCN&#xff0…

解决方案|构建生物医学科技桥梁:镭速客户案例分享

随着生物科技在医学领域的快速发展&#xff0c;数据传输在实现医疗创新和科学研究中的重要性变得日益突出。数据不仅庞大&#xff0c;而且高度敏感&#xff0c;传统的数据传输方式已经无法满足医学行业对高效、快速的数据交流需求。 如今市场上备受关注的解决方案是基于UDP传输…

计算机毕业设计 基于SpringBoot的校园闲置物品交易系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

【gmsh源码阅读】OCC对象绑定tag及获取几何与网格映射关系

一、Tag是什么&#xff1f; gmsh中的几何模型相对于OCC的模型增加了id编号&#xff0c;也叫tag&#xff0c;在gmsh中可以显示出来。在gmsh中&#xff0c;点、线、面、体都有Tag&#xff0c;以方便对其查找定位查找。在OCC中TopoDS_Shape只有几何与拓扑结构&#xff0c;没有唯一…

数据中心代理IP:最优性价比业务应用指南

数据中心代理IP在应对高速高并发的业务时&#xff0c;以独特的高速传输&#xff0c;游刃有余地应对多任务处理&#xff0c;适合于特定业务场景的高效加速。理性选用数据中心代理IP&#xff0c;可以为业务将迎来更加稳健和迅速的发展。今天&#xff0c;我们将揭示数据中心代理IP…

【Linux】分区向左扩容的方法

文章目录 为什么是向左扩容操作前的备份方法&#xff1a;启动盘试用Ubuntu后进行操作 为什么是向左扩容 Linux向右扩容非常简单&#xff0c;无论是系统自带的disks工具还是apt安装的gparted工具&#xff0c;都有图像化的界面可以操作。但是&#xff0c;都不支持向左扩容。笔者…

MC3172 串口模块

MC3172 支持12个串口对应关系如下 串口模块初始化 第一个是uart0~11 inpin RX 脚 管脚号 outpin TX脚 管脚号 baud 波特率 read_ptr ,数据读取指针 void uart_init(u32 uart_num,u8 in_pin,u8 out_pin,u32 baud,u8* read_ptr) {INTDEV_SET_CLK_RST(uart_num,(INTDEV_RUN|…

《动手学深度学习(PyTorch版)》笔记4.6

注&#xff1a;书中对代码的讲解并不详细&#xff0c;本文对很多细节做了详细注释。另外&#xff0c;书上的源代码是在Jupyter Notebook上运行的&#xff0c;较为分散&#xff0c;本文将代码集中起来&#xff0c;并加以完善&#xff0c;全部用vscode在python 3.9.18下测试通过。…

MyBatis详解(3)-- 动态代理及映射器

MyBatis详解&#xff08;3&#xff09; mybatis 动态代理动态代理的规范selectOne和selectListnamespace mybatis映射器映射器的引入&#xff1a; 映射器的组成select 元素结构&#xff1a;单个参数传递多个参数传递 insert 元素结构主键回填&#xff1a;自定义主键生成规则 u …