0
点赞
收藏
分享

微信扫一扫

Spring Boot集成JWT快速入门demo

LeetCode-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 仅包含小写字母

解题思路一:滑动窗口 + 数组

  1. 因为字符串中的字符全是小写字母,可以用长度为26的数组记录字母出现的次数
  2. 设n = len(s), m = len§。记录p字符串的字母频次p_cnt,和s字符串前m个字母频次s_cnt
  3. 若p_cnt和s_cnt相等,则找到第一个异位词索引 0
  4. 继续遍历s字符串索引为[m, n)的字母,在s_cnt中每次增加一个新字母,去除一个旧字母
  5. 判断p_cnt和s_cnt是否相等,相等则在返回值res中新增异位词索引 i - m + 1
class Solution:
    def findAnagrams(self, s: str, p: str) -> List[int]:
        n, m, result = len(s), len(p), []
        if n < m:
            return result
        p_cnt = [0] * 26
        s_cnt = [0] * 26
        for i in range(m):
            p_cnt[ord(p[i]) - ord('a')] += 1
            s_cnt[ord(s[i]) - ord('a')] += 1
        if s_cnt == p_cnt:
            result.append(0)
        
        for i in range(m, n):
            s_cnt[ord(s[i-m]) - ord('a')] -= 1
            s_cnt[ord(s[i]) - ord('a')] += 1
            if s_cnt == p_cnt:
                result.append(i-m+1)

        return result

时间复杂度:O(n)
空间复杂度:O(1)

解题思路二:滑动窗口 + 双指针

除了直接比较数组是否相等外,其实还可以用双指针来表示滑动窗口的两侧边界,当滑动窗口的长度等于p的长度时,表示找到一个异位词,两种方式的时间复杂度都是O(n)级别的
先说结论,Python用数组更快一点点(差不太多其实),Java用双指针更快一点,下面是具体步骤:

  1. 定义滑动窗口的左右两个指针left,right
  2. right一步一步向右走遍历s字符串
  3. right当前遍历到的字符加入s_cnt后不满足p_cnt的字符数量要求,将滑动窗口左侧字符不断弹出,也就是left不断右移,直到符合要求为止。
  4. 当滑动窗口的长度等于p的长度时,这时的s子字符串就是p的异位词。
    其中,left和right表示滑动窗口在字符串s中的索引,cur_left和cur_right表示字符串s中索引为left和right的字符在数组中的索引
class Solution:
    def findAnagrams(self, s: str, p: str) -> List[int]:
        n, m, res = len(s), len(p), []
        if n < m: return res
        p_cnt = [0] * 26
        s_cnt = [0] * 26

        for i in range(m):
            p_cnt[ord(p[i]) - ord('a')] += 1
        
        left = 0
        for right in range(n):
            cur_right = ord(s[right]) - ord('a')
            s_cnt[cur_right] += 1
            while s_cnt[cur_right] > p_cnt[cur_right]:
                cur_left = ord(s[left]) - ord('a')
                s_cnt[cur_left] -= 1
                left += 1
            if right - left + 1 == m:
                res.append(left)
        return res

时间复杂度:O(n)
空间复杂度:O(1)

解题思路三:0


时间复杂度:O(n)
空间复杂度:O(n)

举报

相关推荐

0 条评论