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

题目

438. 找到字符串中所有字母异位词
给定一个字符串 s 和一个非空字符串 p,找到 s 中所有是 p 的字母异位词的子串,返回这些子串的起始索引。

字符串只包含小写英文字母,并且字符串 s 和 p 的长度都不超过 20100。

说明:

字母异位词指字母相同,但排列不同的字符串。
不考虑答案输出的顺序。
示例 1:

输入:
s: "cbaebabacd" p: "abc"

输出:
[0, 6]

解释:
起始索引等于 0 的子串是 "cba", 它是 "abc" 的字母异位词。
起始索引等于 6 的子串是 "bac", 它是 "abc" 的字母异位词。

思路

此题也是滑动窗口的题目,一样的套路,写模板,回答问题

扩大窗口需要做什么操作?
什么条件下缩小窗口?
缩小窗口之后做什么操作?
结果在扩大窗口还是缩小窗口处更新?
然后依次填入即可。

扩大窗口需要做什么操作?-----更新windows增加值,判断是windows中和need的的新增值是否相等,相等则计数+1
什么条件下缩小窗口?-----缩小窗口条件为 窗口大小和目标字符串一样大时(为了保证窗口的大小)
缩小窗口之后做什么操作?-----更新windows减少值,判断是windows中和need的的新增值是否相等,相等则计数-1
结果在扩大窗口还是缩小窗口处更新?------因为要子串,所以在缩小窗口之前更新(需要判断下窗口中的计数和need大小是否相等)

class Solution {
    public List<Integer> findAnagrams(String s, String p) {
        ArrayList<Integer> ret = new ArrayList<>();
        HashMap<Character,Integer> windows = new HashMap<>();
        HashMap<Character,Integer> need = new HashMap<>();
        int left = 0, right = 0;
        int vaild = 0;
        for (int i = 0; i < p.length(); i++) {
            need.put(p.charAt(i), need.getOrDefault(p.charAt(i), 0 )+1);
        }
        while (right<s.length()){
            char c = s.charAt(right);
            right++;
            windows.put(c, windows.getOrDefault(c, 0)+1);
            if(windows.get(c).equals(need.get(c))){
                vaild++;
            }
            while (right-left==p.length()){
                if(vaild==need.size()){
                    ret.add(left);
                }
                char d = s.charAt(left);
                left++;
                if(windows.get(d).equals(need.get(d))){
                    vaild--;
                }
                windows.put(d, windows.getOrDefault(d,0)-1);
            }
        }
        return ret;
    }
}
posted @ 2021-04-15 20:48  火颜  阅读(50)  评论(0)    收藏  举报