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

77 阅读1分钟

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" 的异位词。

 

提示:

  • 1 <= s.length, p.length <= 3 * 104
  • s 和 p 仅包含小写字母

知识点 滑动窗口 + hash表

代码

def findAnagrams(s, p):
    ls = len(s)
    lp = len(p)
    if lp > ls:
        return []
    # 0. 滑动窗口 + hash表
    tp = [0 for _ in range(26)] # 存放26个字母的计数
    ts = [0 for _ in range(26)]
    ans = []
    # - 先统计到p这么长
    for i in range(lp):
        tp[ord(p[i]) - ord('a')] += 1
        ts[ord(s[i]) - ord('a')] += 1
    if tp == ts :
        ans.append(0) # 初始段
    # - 再从p长度的地方往后滑
    for i in range(lp , ls):
        ts[ord(s[i - lp]) - ord('a')] -= 1 #头出尾进
        ts[ord(s[i]) - ord('a')] += 1
        if ts == tp:
            ans.append(i - lp + 1)
    return ans

    '''
    # 1. 暴力算法
    ans = []
    tp = sorted(p)
    for i in range(ls - lp + 1):
        ts = sorted(s[i:i + lp])
        if tp[0] == ts[0]:
            if tp == ts:
                ans.append(i)
    return ans
    '''
    '''
    # 2. 滑动窗口 + hash表,这种和暴力算法一样慢
    ans = []
    i = 0
    j = 0
    dp = collections.defaultdict(int)
    ds = collections.defaultdict(int)
    while j < ls:
        ds[s[j]] += 1
        while ds[s[j]] > dp[s[j]]:
            ds[s[i]] -= 1
            i += 1
        ans.append(i)

    return ans
    '''