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

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

这个解题思路的核心是利用固定大小的滑动窗口数组统计字符频率来高效判断子串是否为异位词。以下是详细解释:

1. 核心思路

  • 异位词的定义:两个字符串包含的字符及其数量完全相同,只是顺序可能不同。例如,“abc” 和 “bca” 是异位词。
  • 滑动窗口的适用性:由于异位词的长度必须与原字符串相同,因此可以在 s 中滑动一个长度为 p.size() 的窗口,逐一检查窗口内的字符频率是否与 p 一致。

2. 算法步骤

步骤1:预处理字符频率数组
  • 创建两个长度为 26 的数组(假设只包含小写字母):
    • target[26]:统计 p 中每个字符的出现次数。
    • window[26]:统计当前窗口中每个字符的出现次数。
步骤2:初始化第一个窗口
  • 遍历 s 的前 p.size() 个字符,将字符频率填入 window 数组。
步骤3:滑动窗口并检查匹配
  • 固定窗口大小:窗口始终保持长度为 p.size()
  • 每次滑动
    1. 右移窗口:将右侧新字符加入窗口(更新 window 数组)。
    2. 移出左侧字符:将左侧旧字符移出窗口(更新 window 数组)。
    3. 检查匹配:比较 windowtarget 是否完全相同。若相同,则记录当前窗口的起始位置。

3. 关键优化点

用数组替代哈希表
  • 由于字符集较小(26个小写字母),使用数组比哈希表更高效。数组的随机访问时间复杂度为 O(1),且无需处理哈希冲突。
固定窗口大小
  • 窗口大小始终等于 p.size(),避免了动态调整窗口的复杂性,简化了逻辑。
快速比较数组
  • 直接比较两个数组(window == target)的时间复杂度为 O(26) = O(1),因为数组长度固定。

4. 处理特殊情况

  • s.size() < p.size():直接返回空结果,因为无法构造有效窗口。

5. 复杂度分析

  • 时间复杂度:O(n),其中 n 是 s 的长度。每个字符仅被访问两次(加入窗口和移出窗口)。
  • 空间复杂度:O(1),因为数组大小固定为 26,不随输入长度变化。

6. 示例代码(参考力扣官方题解)

vector<int> findAnagrams(string s, string p) {vector<int> result;if (s.size() < p.size()) return result;vector<int> target(26, 0);vector<int> window(26, 0);// 统计p中字符频率for (char c : p) target[c - 'a']++;// 初始化第一个窗口for (int i = 0; i < p.size(); i++) {window[s[i] - 'a']++;}// 检查第一个窗口if (window == target) result.push_back(0);// 滑动窗口for (int i = p.size(); i < s.size(); i++) {// 移出左侧字符window[s[i - p.size()] - 'a']--;// 移入右侧字符window[s[i] - 'a']++;// 检查当前窗口if (window == target) result.push_back(i - p.size() + 1);}return result;
}

7. 与你的测试用例的关系

在你的测试用例中,sp 都很长,但主要由 a 组成。上述算法通过固定窗口大小和数组统计,能高效处理这种情况,避免了频繁哈希表操作的开销。每次滑动窗口只需 O(1) 时间更新频率并比较数组,因此即使字符串很长,也能快速找到所有异位词位置。

http://www.xdnf.cn/news/7991.html

相关文章:

  • Linux `nc` 命令详细讲解
  • vue3:十四、角色权限管理-表格引入-树形表格
  • Axure系统原型设计列表版方案
  • BERT框架:自然语言处理的革命性突破
  • PostgreSQL 14 pacemaker 高可用集群
  • czml数据以及应用
  • uniapp打包报错:重新在manifest.json中生成自己的APPID
  • MacBookPro上macOS安装第三方应用报错解决方案:遇到:“无法打开“XXX”,因为无法确定(验证)开发者身份?怎么解决
  • Android 网络全栈攻略(三)—— 从三方库原理来看 HTTP
  • 代码走读 Go 语言 Map 的实现
  • MAX96752FGTN/V+T:双LVDS(OLDI)输出的GMSL2解串器架构与应用探讨——汽车与工业视频传输方案深度分析
  • 新能源汽车移动充电服务:如何通过智能调度提升充电桩可用率?
  • 从零基础到最佳实践:Vue.js 系列(9/10):《单元测试与端到端测试》
  • Elasticsearch 分页查询的 from+size 有什么缺陷?如何优化深度分页?比较scroll API与search_after的差异
  • 软考中级软件设计师——设计模式篇
  • window 显示驱动开发-指定 GDI 硬件加速渲染操作
  • WebRTC:实时通信的未来之路
  • redis搭建最小的集群,3主3从
  • Android-ViewModel+LiveData学习总结
  • Python爬虫实战:研究Grab 框架相关技术
  • HTTP Digest 认证:原理剖析与服务端实现详解
  • 如何开发一个MCP Server
  • Google机器学习实践指南(梯度下降篇)
  • 关于pgSQL配置后Navicat连接不上的解决方法
  • JAVA开发工具延长方案
  • 大模型在闭合性胫骨平台骨折诊疗全流程中的应用研究报告
  • MySql添加非空字段时的“伪空”问题
  • Elasticsearch搜索排名优化
  • 如何在 Mac M4 芯片电脑上卸载高版本的 Node.js
  • el-radio-group 与 el-dropdown 组合使用的注意事项