题目
给定一个字符串 s 和一个非空字符串 p,找到 s 中所有是 p 的字母异位词的子串,返回这些子串的起始索引。
字符串只包含小写英文字母,并且字符串 s 和 p 的长度都不超过 20100。
示例:
示例一: 输入: s: "cbaebabacd" p: "abc" 输出: [0, 6] 解释: 起始索引等于 0 的子串是 "cba", 它是 "abc" 的字母异位词。 起始索引等于 6 的子串是 "bac", 它是 "abc" 的字母异位词。 示例二: 输入: s: "abab" p: "ab" 输出: [0, 1, 2] 解释: 起始索引等于 0 的子串是 "ab", 它是 "ab" 的字母异位词。 起始索引等于 1 的子串是 "ba", 它是 "ab" 的字母异位词。 起始索引等于 2 的子串是 "ab", 它是 "ab" 的字母异位词。 说明:
- 字母异位词指字母相同,但排列不同的字符串。
- 不考虑答案输出的顺序。
题解
本题解法与参考一致,采用滑动窗口法进行求解。
class Solution { public List<Integer> findAnagrams(String s, String p) { //采用滑动窗口法进行求解,思路与76题最小覆盖字串一样 if(s.length() < p.length()){ return new ArrayList<>(); } int left = 0; int right = 0; Map<Character, Integer> window = new HashMap<>(); Map<Character, Integer> need = new HashMap<>(); int len = 0; //记录匹配字符长度 List<Integer> list = new ArrayList<>(); 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 c1 = s.charAt(right); if(need.containsKey(c1)){ window.put(c1, window.getOrDefault(c1, 0) + 1); if(window.get(c1).intValue() == need.get(c1).intValue()){ len++; } } right++; while(len == need.size()){ char c2 = s.charAt(left); if((right - left) == p.length()){ list.add(left); } if(need.containsKey(c2)){ window.put(c2, window.get(c2) - 1); if(window.get(c2).intValue() < need.get(c2).intValue()){ len--; } } left++; } } return list; } }