leetcode438. 找到字符串中所有字母异位词
题目描述
链接: leetcode438.
给定两个字符串 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)初始化左右指针left和right,并使用两个map分别记录模式串和当前窗口[left, right]出现的字符及次数。
(2)不断地增加right指针扩大窗口[left, right],直到窗口中的字符串符合要求(包含了 T 中的所有字符)
(3)停止增加right,转而不断增加left指针缩小窗口[left, right],直到窗口中的字符串不再符合要求(不包含 T 中的所有字符了)。同时,每次增加 left,更新一轮结果。
(4)重复第 2 和第 3 步,直到 right 到达字符串s的尽头。
- java解法
public class FindAnagrams438 {
public List<Integer> findAnagrams(String s, String p) {
List<Integer> res = new ArrayList<>();
Map<Character, Integer> window = new HashMap<>();
Map<Character, Integer> origin = new HashMap<>();
int pLen = p.length();
for (int i = 0; i < pLen; ++i) {
char ch = p.charAt(i);
origin.put(ch, origin.getOrDefault(ch, 0) + 1);
}
int left = 0;
int right = -1;
int sLen = s.length();
while (right < sLen) {
right++;
while (right < sLen && origin.containsKey(s.charAt(right))) {
window.put(s.charAt(right), window.getOrDefault(s.charAt(right), 0) + 1);
}
while (isValidWindow(origin, window) && left <= right) {
if (origin.size() == window.size()) {
res.add(left);
}
if (origin.containsKey(s.charAt(left))) {
window.put(s.charAt(left), window.getOrDefault(s.charAt(left), 0) - 1);
}
left++;
}
}
return res;
}
public boolean isValidWindow(Map<Character, Integer> ori, Map<Character, Integer> win) {
for (Map.Entry<Character, Integer> entry : ori.entrySet()) {
Character key = entry.getKey();
Integer val = entry.getValue();
if (win.getOrDefault(key, 0) < val) {
return false;
}
}
return true;
}
}
- golang解法
func findAnagrams(s string, p string) []int {
var res []int
origin, window, left, right := map[byte]int{}, map[byte]int{}, 0, 0
for i := 0; i < len(p); i++ {
origin[p[i]]++
}
for right < len(s) {
window[s[right]]++
for window[s[right]] > origin[s[right]] {
window[s[left]]--
left++
}
if right - left + 1 == len(p) {
res = append(res, left)
}
right++
}
return res
}