LeetCode 热题100 438. 找到字符串中所有字母异位词

ops/2025/3/3 14:53:33/

LeetCode 热题100 | 438. 找到字符串中所有字母异位词

大家好,今天我们来解决一道经典的算法题——找到字符串中所有字母异位词。这道题在 LeetCode 上被标记为中等难度,要求我们在字符串 s 中找到所有是 p 的异位词的子串,并返回这些子串的起始索引。下面我将详细讲解解题思路,并附上 Python 代码实现。


题目描述

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

示例:

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

解题思路

这道题的核心是找到 s 中所有与 p 的字符组成相同的子串。我们可以使用 滑动窗口哈希表 来解决这个问题。

核心思想

  1. 滑动窗口

    • 使用一个固定大小的窗口(大小为 p 的长度)在 s 上滑动。
    • 检查窗口内的字符是否与 p 的字符组成相同。
  2. 哈希表

    • 使用两个哈希表(或数组)分别记录 p 的字符频率和当前窗口的字符频率。
    • 如果两个哈希表相等,则当前窗口是 p 的异位词。

代码实现

from collections import defaultdictdef findAnagrams(s, p):""":type s: str:type p: str:rtype: List[int]"""result = []  # 存储结果的起始索引len_s, len_p = len(s), len(p)# 如果 s 的长度小于 p 的长度,直接返回空列表if len_s < len_p:return result# 初始化 p 的字符频率哈希表p_count = defaultdict(int)for char in p:p_count[char] += 1# 初始化滑动窗口的字符频率哈希表window_count = defaultdict(int)for i in range(len_p):window_count[s[i]] += 1# 滑动窗口for i in range(len_s - len_p + 1):# 如果当前窗口的字符频率与 p 的字符频率相等,记录起始索引if window_count == p_count:result.append(i)# 移动窗口if i + len_p < len_s:  #如果 i + len_p >= len_s,说明窗口已经到达 s 的末尾,无法再向右移动。window_count[s[i]] -= 1if window_count[s[i]] == 0:del window_count[s[i]]window_count[s[i + len_p]] += 1return result

代码解析

  1. 初始化

    • 如果 s 的长度小于 p 的长度,直接返回空列表。
    • 使用 defaultdict 初始化 p 的字符频率哈希表 p_count
  2. 滑动窗口

    • 初始化滑动窗口的字符频率哈希表 window_count,记录窗口内的字符频率。
    • 遍历 s,每次移动窗口时:
      • 如果 window_countp_count 相等,则当前窗口是 p 的异位词,记录起始索引。
      • 移动窗口:移除左边界字符,加入右边界字符。
  3. 返回结果

    • 返回所有符合条件的起始索引。

复杂度分析

  • 时间复杂度:O(n),其中 n 是字符串 s 的长度。我们只需要遍历 s 一次。
  • 空间复杂度:O(1),因为字符集大小固定(小写字母,最多 26 个),哈希表的大小是常数。

示例运行

示例 1

# 输入: s = "cbaebabacd", p = "abc"
s = "cbaebabacd"
p = "abc"
print(findAnagrams(s, p))  # 输出: [0, 6]

解释

  • 起始索引等于 0 的子串是 "cba",它是 "abc" 的异位词。
  • 起始索引等于 6 的子串是 "bac",它是 "abc" 的异位词。

示例 2

# 输入: s = "abab", p = "ab"
s = "abab"
p = "ab"
print(findAnagrams(s, p))  # 输出: [0, 1, 2]

解释

  • 起始索引等于 0 的子串是 "ab",它是 "ab" 的异位词。
  • 起始索引等于 1 的子串是 "ba",它是 "ab" 的异位词。
  • 起始索引等于 2 的子串是 "ab",它是 "ab" 的异位词。

总结

通过滑动窗口和哈希表,我们可以高效地找到 s 中所有是 p 的异位词的子串。这种方法的时间复杂度为 O(n),空间复杂度为 O(1),能够处理较大的输入规模。希望这篇题解对你有帮助!如果还有其他问题,欢迎继续提问!

关注我,获取更多算法题解和编程技巧!


http://www.ppmy.cn/ops/162788.html

相关文章

Linux(centOS) 命令提示符格式修改(PS1)

1. 命令提示符的组成 命令提示符&#xff08;PS1&#xff09;通常由以下部分组成&#xff1a; 部分示例说明[ 和 ][...]提示符的开头和结尾&#xff0c;用于视觉分隔。用户名root 或 tianjiajie当前登录的用户。root 是超级用户&#xff0c;普通用户可能是其他名称。分隔用户…

16.11 LangChain SQL 生成与执行实战:构建安全高效的数据库查询引擎

LangChain SQL 生成与执行实战:构建安全高效的数据库查询引擎 关键词:SQL 安全执行、数据库连接池、查询结果处理、错误重试机制、生产级 SQL 运维 1. SQL 执行全链路架构设计 1.1 核心处理流程图 #mermaid-svg-2aWgNUpLctOECv8J {font-family:"trebuchet ms",ve…

ARM Linux LCD上实时预览摄像头画面

文章目录 1、前言2、环境介绍3、步骤4、应用程序编写4.1、lcd初始化4.2、摄像头初始化4.3、jpeg解码4.4、开启摄像头4.5、完整的程序如下 5、测试5.1、编译应用程序5.2、运行应用程序 6、总结 1、前言 本次应用程序主要针对支持MJPEG格式输出的UVC摄像头。 2、环境介绍 rk35…

react 编写一个待办事项,函数优化,组件传值

待办事项 Import react {component} from ‘react’ Class TodoList extend component{ Costructor(props){ Super(props); This.state{ Value””, List:[] } } getValue(e){ Let valuee.target.value; This.setState({ value }) } addValue(){ This.setState({ List:[...thi…

conda 更换镜像究极方法

conda安装软件一直用的北外镜像&#xff0c;但是我租的服务器机构IP好像最近被屏蔽了&#xff0c;一直无法使用。机构内部搭了本地镜像。 在更换本地镜像&#xff08;修改.condarc文件&#xff09;后&#xff0c;新建环境可以正常使用本地镜像&#xff0c;但是之前建的环境依旧…

dify基础之prompts

摘要&#xff1a;在大型语言模型&#xff08;LLM&#xff09;应用中&#xff0c;Prompt&#xff08;提示词&#xff09;是连接用户意图与模型输出的核心工具。本文从概念、组成、设计原则到实践案例&#xff0c;系统讲解如何通过Prompt解锁LLM的潜能&#xff0c;提升生成内容的…

MAC M1 Pro 安装docker desktop 无法启动

MAC M1 Pro 安装docker desktop 无法启动 今天安装docker desktop&#xff0c;结果反反复复安装了很多遍&#xff0c;总是启动不成功&#xff0c;桌面启动好久然后弹出下图错误&#xff1a; 我先是按照一些解决方案尝试了比如https://dev59.com/mlEG5IYBdhLWcg3wP35V 卸载重…

如何安装配置Goland并使用固定公网地址SSH远程连接本地服务器

文章目录 1. 安装配置GoLand2. 服务器开启SSH服务3. GoLand本地服务器远程连接测试4. 安装cpolar内网穿透远程访问服务器端 4.1 服务器端安装cpolar4.2 创建远程连接公网地址 5. 使用固定TCP地址远程开发 本文主要介绍使用GoLand通过SSH远程连接服务器&#xff0c;并结合cpol…