438. 找到字符串中所有字母异位词(中)
题目
- 给定两个字符串 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" 的异位词。
题解:滑动窗口
python
class Solution:
def findAnagrams(self, s: str, t: str) -> List[int]:
need={}# 存储字符串 t 中各个字符的需求量
window={}# 存储滑动窗口中各个字符的出现次数
for c in t:#遍历字符串t
need.setdefault(c,0)#访问不存在的键时自动创建并将值设置为 0
need[c]+=1# 统计字符串 t 中各个字符的需求量
left=0# 滑动窗口的左指针
right=0# 滑动窗口的右指针
valid=0# 记录满足需求的字符数
res=[]#结果列表
while right<len(s):
c=s[right]# 当前字符
right+=1# 右指针右移
if c in need:#当前字符是目标字符中的
window.setdefault(c,0)#访问不存在的键时自动创建并将值设置为 0
window[c]+=1# 更新滑动窗口中当前字符的出现次数
if window[c]==need[c]:
valid+=1# 如果滑动窗口中当前字符的出现次数达到需求量,增加满足需求的字符数
while valid==len(need):#每个字符的次数都达到了要求
if right-left==len(t):#数量也是相等的话
res.append(left)#把第一个索引的坐标加入结果列表
d=s[left]# 将要移出窗口的字符
left+=1# 左指针右移
if d in need:#当前字符是目标字符中的
if window[d]==need[d]:#如果滑动窗口中当前字符等于目标字符的值
valid-=1# 如果移出窗口的字符导致窗口不再满足需求,则减少满足需求的字符数
window[d]-=1# 更新滑动窗口中移出字符的出现次数
return res#返回结果列表
javascript
- 思路:要在s中找到字符串p的异位词,相当于对s按固定长度的窗口滑动,窗口内的元素与s中元素出现的次数相等就把窗口左指针下标加入结果数组
var findAnagrams = function(s, p) {
const sLen = s.length, pLen = p.length; // 获取s和p的长度
if (sLen < pLen) { // 如果s的长度小于p的长度,返回空数组
return [];
}
const ans = []; // 结果数组,用于存储找到的起始索引
const sCount = new Array(26).fill(0); // 初始化s中每个字母的计数数组
const pCount = new Array(26).fill(0); // 初始化p中每个字母的计数数组
// 记录p的每个字母出现次数,同时记录s的前pLen个字母出现次数
for (let i = 0; i < pLen; ++i) {
//s[i]的ASCII码减去a的ASCII码的值作为sCount索引
++sCount[s[i].charCodeAt() - 'a'.charCodeAt()]; // 统计s中当前字母出现次数
++pCount[p[i].charCodeAt() - 'a'.charCodeAt()]; // 统计p中当前字母出现次数
}
// 如果s的前pLen个字母与p的字母出现次数相同,则记录起始索引0
//下面循环窗口已经向右滑动,滑动前就应该正确处理第一个窗口
if (sCount.toString() === pCount.toString()) {
ans.push(0);
}
// 从s的pLen到sLen遍历,检查每个窗口的字母计数
for (let i = 0; i < sLen - pLen; ++i) {
// 移动窗口:减少当前字母的计数,增加新字母的计数
--sCount[s[i].charCodeAt() - 'a'.charCodeAt()]; // 减去s中当前字母的计数
++sCount[s[i + pLen].charCodeAt() - 'a'.charCodeAt()]; // 增加s中下一个字母的计数
// 检查当前窗口的字母计数是否与p的字母计数相同
if (sCount.toString() === pCount.toString()) {
ans.push(i + 1); // 记录当前窗口的起始索引(i + 1)
}
}
return ans; // 返回所有找到的起始索引
};
标签:
力扣
, 力扣hot100-js
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了