问题:给定两个字符串 s
和 p
,找到 s
中所有 p
的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。
package com.text;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.alibaba.fastjson.JSONObject;
public class findAnagrams {
public static void main(String[] args) {
findAnagrams("cbaebabacd","abc");
}
public static List<Integer> findAnagrams(String s, String p) {
List<Integer> list=new ArrayList<Integer>();
int slen=s.length();
int plen=p.length();
//p的长度大于s就返回
if(plen>slen){
return list;
}
//将p的字符存储到map中,key是字符,value是出现的次数
Map<Character,Integer> pMap=new HashMap<Character,Integer>();
for(int i=0;i<p.length();i++){
Integer pNum=pMap.getOrDefault(p.charAt(i), 0);
pMap.put(p.charAt(i),pNum+1);
}
//截取s串的起始坐标
int endIndex=0;
//存储截取的S串中字符出现的次数
Map<Character,Integer> sMap=new HashMap<Character,Integer>();
while(endIndex+plen<=slen){
String substr= s.substring(endIndex,endIndex+plen);
//下标等于0的时候需要全量存储
if(endIndex==0){
for(int i=0;i<substr.length();i++){
Integer sNum=sMap.getOrDefault(substr.charAt(i), 0);
sMap.put(substr.charAt(i),sNum+1);
}
}else{
//不等于0的时候相当于下标右移
//前一个元素出现次数需要减1,如果次数等于0需要移除,否则影响相等的校验
//最后一个需要加1
char removeKey = s.charAt(endIndex-1);
Integer sNum=sMap.getOrDefault(removeKey, 0);
if(sNum-1==0) {
sMap.remove(removeKey);
}else {
sMap.put(removeKey,sNum-1);
}
char addKey = substr.charAt(plen-1);
Integer sNum1=sMap.getOrDefault(addKey, 0);
sMap.put(addKey,sNum1+1);
}
//判断是否相等两个map
//会进行key和value的全变比较
if(sMap.equals(pMap)) {
list.add(endIndex);
}
endIndex++;
}
System.out.println(JSONObject.toJSONString(list));
return list;
}
}