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

问题链接:

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

问题描述:

给定两个字符串 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:

算法思想:

  1. 把查询数据p进行从大到小排序,
  2. 对原数组进行遍历,并且规定范围,len(s)-l+1:减少遍历次数,因为后面都不满足p的长度。
  3. 随后开始遍历,初始坐标为i,选取i到i+l的区间,进行排序,是否相等。
  4. 相等则输入列表。
#类似于暴力。非常慢
class Solution:
    def findAnagrams(self, s: str, p: str) -> List[int]:
        l=len(p)
        p=sorted(p)
        ans=[]
        c=[]
        for i in range(0,len(s)-l+1):
            c=sorted(s[i:i+l])
            if c==p:
                ans.append(i)
        return ans

代码2:

利用不定长滑动窗口的思想。

  1. 利用Counter计数器对p进行字母的统计。
  2. 随后遍历数组s,并将遍历的值c放入计数器cnt中,有这个数据则减一。
  3. 如果发现cnt[c]<0,则可以判断字母c太多,所以需要回复s[left]的cnt中的值,滑动窗口left向前进一。
  4. 最后一步,判断坐标长度是否满足p的长度,满足,则输入left。
#不定长
class Solution:
    def findAnagrams(self, s: str, p: str) -> List[int]:
        ans=[]
        cnt=Counter(p)
        left=0
        for right,c in enumerate(s):
            cnt[c]-=1
            while cnt[c]<0:  #字母c太多了
                cnt[s[left]]+=1  #左端点字母离开窗口
                left+=1
            if right-left+1==len(p):
                ans.append(left)
        return ans

代码3:

定长滑动窗口:

  1. 右指针每移动一位就增加当前字符计数
  2. 计算左指针位置,当窗口长度达标时:
  3. 比较当前窗口与目标p的字符分布,若匹配则将左指针加入结果
  4. 窗口右移前减少左指针字符计数
  5. 通过动态维护的字符计数器实现O(n)时间复杂度
#定长
class Solution:
    def findAnagrams(self, s: str, p: str) -> List[int]:
        ans=[]
        cnt_p=Counter(p)
        cnt_s=Counter()
        for right,c in enumerate(s):
            cnt_s[c]+=1
            left=right-len(p)+1  #确定left的下标
            if left<0:
                continue   #当要验证的数据没有满足的时候,跳过下面继续运作
            if cnt_s==cnt_p:   #s和p的每种字母的出现次数都相同
                ans.append(left)  #s左端点下标加入答案
            cnt_s[s[left]]-=1  #左端点字母离开窗口
        return ans
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值