package leecode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 438. 找到字符串中所有字母异位词
*
* 给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。
*
* 异位词 指由相同字母重排列形成的字符串(包括相同的字符串)。
*
*
* @author Tang
* @date 2021/12/6
*/
public class FindAnagrams {
/**
* 滑动窗口
*
* @param s
* @param p
* @return
*/
public List<Integer> findAnagrams(String s, String p) {
char[] all = s.toCharArray();
char[] target = p.toCharArray();
List<Integer> result = new ArrayList<>();
//构建needMap
Map<Character, Integer> needMap = new HashMap<>();
for (char c : target) {
needMap.put(c, needMap.getOrDefault(c, 0) + 1);
}
//构建window
Map<Character, Integer> window = new HashMap<>();
//窗口左右指针
//窗口左毕右开原则
int left = 0;
int right = 0;
//当前窗口中满足了 有几个元素满足了need需要的数量
// 0 <= valid <= needMap.size
int valid = 0;
//以窗口右边界走到头为限制
while(right < all.length) {
char c = all[right];
right++;
//判断c是否需要
if(needMap.containsKey(c)) {
window.put(c, window.getOrDefault(c, 0) +1);
//判断c元素是否达到需求数量
if(window.get(c).equals(needMap.get(c))) {
valid++;
}
}
//判断左缩窗口条件
if(right - left == target.length) {
//判断是否满足need全部要求
//加入结果
if(valid == needMap.size()) {
result.add(left);
}
//左缩窗口
char d = all[left];
left++;
if(needMap.containsKey(d)) {
if(window.get(d).equals(needMap.get(d))) {
valid--;
}
window.put(d, window.get(d) - 1);
}
}
}
return result;
}
public static void main(String[] args) {
}
}