美文网首页
438. 找到字符串中所有字母异位词--滑动窗口

438. 找到字符串中所有字母异位词--滑动窗口

作者: zhi5ai | 来源:发表于2024-09-17 13:59 被阅读0次

438. 找到字符串中所有字母异位词 - 力扣(LeetCode)

class Solution {
    public List<Integer> findAnagrams(String s, String p) {
        int sLen = s.length(), pLen = p.length();

        if (sLen < pLen) {
            return new ArrayList<Integer>();
        }

        List<Integer> ans = new ArrayList<Integer>();
        int[] sCount = new int[26];
        int[] pCount = new int[26];
//初始化窗口
        for (int i = 0; i < pLen; ++i) {
            ++sCount[s.charAt(i) - 'a'];
            ++pCount[p.charAt(i) - 'a'];
        }
//判断初始化窗口是否为 异位词
        if (Arrays.equals(sCount, pCount)) {
            ans.add(0);
        }
//开始滑动s上的窗口,判断是否为异位词
        for (int i = 0; i < sLen - pLen; ++i) {
            --sCount[s.charAt(i) - 'a'];
            ++sCount[s.charAt(i + pLen) - 'a'];

            if (Arrays.equals(sCount, pCount)) {
                ans.add(i + 1);
            }
        }

        return ans;
    }
}
复杂度分析

时间复杂度:O(m+(n−m)×Σ),其中 n 为字符串 s 的长度,m 为字符串 p 的长度,Σ 为所有可能的字符数。我们需要 O(m) 来统计字符串 p 中每种字母的数量;需要 O(m) 来初始化滑动窗口;需要判断 n−m+1 个滑动窗口中每种字母的数量是否与字符串 p 中每种字母的数量相同,每次判断需要 O(Σ) 。因为 s 和 p 仅包含小写字母,所以 Σ=26。

空间复杂度:O(Σ)。用于存储字符串 p 和滑动窗口中每种字母的数量。

方法二 优化的滑动窗口

differ 来记录当前窗口与字符串 p 中数量不同的字母的个数
滑动窗口
s:source p:target

class Solution {
    public List<Integer> findAnagrams(String s, String p) {
        int sLen = s.length(), pLen = p.length();

        if (sLen < pLen) {
            return new ArrayList<Integer>();
        }

        List<Integer> ans = new ArrayList<Integer>();
        int[] count = new int[26];
1. 初始化滑动窗口
        for (int i = 0; i < pLen; ++i) {
            ++count[s.charAt(i) - 'a'];
            --count[p.charAt(i) - 'a'];
        }
2. 初始化滑动窗口的differ
        int differ = 0;
        for (int j = 0; j < 26; ++j) {
            if (count[j] != 0) {
                ++differ;
            }
        }
3. 判断初始化的滑动窗口是否存在异位词
        if (differ == 0) {
            ans.add(0);
        }
4. 开始向右滑动,并进行比较
        for (int i = 0; i < sLen - pLen; ++i) {
5. 窗口左边界,之前为1,表示s中比p多1,不同,现在窗口收缩减去,等于0,则differ-1;
              之前为0表示相同,现在窗口收缩减去1,等于-1,则differ+1;
                  --》窗口左边界收缩
            if (count[s.charAt(i) - 'a'] == 1) {  // 窗口中字母 s[i] 的数量与字符串 p 中的数量从不同变得相同
                --differ;
            } else if (count[s.charAt(i) - 'a'] == 0) {  // 窗口中字母 s[i] 的数量与字符串 p 中的数量从相同变得不同
                ++differ;
            }
            --count[s.charAt(i) - 'a'];
6. 窗口右边界,动态更新differ
          之前为-1,窗口向右滑动,加1,则等于0,即differ-1
          之前为0,现在如果窗口向右滑动,加1,则等于1,即differ+1
                ==》窗口右边界向右滑动
(判断窗口内每种字母的数量是否与字符串 p 中每种字母的数量相同)
            if (count[s.charAt(i + pLen) - 'a'] == -1) {  // 窗口中字母 s[i+pLen] 的数量与字符串 p 中的数量从不同变得相同
                --differ;
            } else if (count[s.charAt(i + pLen) - 'a'] == 0) {  // 窗口中字母 s[i+pLen] 的数量与字符串 p 中的数量从相同变得不同
                ++differ;
            }
            ++count[s.charAt(i + pLen) - 'a'];
            
            if (differ == 0) {
                ans.add(i + 1);
            }
        }

        return ans;
    }
}
时间复杂度:O(n+m+Σ),其中 n 为字符串 s 的长度,m 为字符串 p 的长度,其中Σ 为所有可能的字符数。我们需要 O(m) 来统计字符串 p 中每种字母的数量;需要 O(m) 来初始化滑动窗口;需要 O(Σ) 来初始化 differ;需要 O(n−m) 来滑动窗口并判断窗口内每种字母的数量是否与字符串 p 中每种字母的数量相同,每次判断需要 O(1) 。因为 s 和 p 仅包含小写字母,所以 Σ=26。

空间复杂度:O(Σ)。用于存储滑动窗口和字符串 p 中每种字母数量的差

相关文章

网友评论

      本文标题:438. 找到字符串中所有字母异位词--滑动窗口

      本文链接:https://www.haomeiwen.com/subject/rwegljtx.html