1、题目描述
给定一个字符串 s
和一个字符串数组 words
。 words
中所有字符串 长度相同。
s
中的 串联子串 是指一个包含 words
中所有字符串以任意顺序排列连接起来的子串。
- 例如,如果
words = ["ab","cd","ef"]
, 那么"abcdef"
,"abefcd"
,"cdabef"
,"cdefab"
,"efabcd"
, 和"efcdab"
都是串联子串。"acdbef"
不是串联子串,因为他不是任何words
排列的连接。
返回所有串联子串在 s
中的开始索引。你可以以 任意顺序 返回答案。
2、算法思路
异位词的长度是和p的长度是固定的。是连续的窗口,所以使用滑动窗口来解决,但是是固定大小的窗口。
并且使用count来记录窗口中的字母的种类和个数。当count中记录的种类和个数和p的种类和个数一样就可以更新结果。可以把s中的每len = word[0].length的长度看成是一个字符。
3、算法流程
因为条件中words
中所有字符串 长度相同指出,所以s中长度是每word[0].length是一个字符,把长度是word[0].length看成是一个字符。⽆⾮就是之前处理的对象是⼀个⼀个的字符,我们这⾥处理的对象是⼀个⼀个的单词。具体我们可以参考LeetCode 438.找到字符串中所有字母异位词-CSDN博客https://blog.csdn.net/EdgeAI/article/details/145023585?spm=1001.2014.3001.5501
4、算法代码
ight+len<=s.length(),需要这一句。是因为判断不能超过索引,需要等于是因为我们是先判断了+len。在第438题,没有这样写是因为麻烦,当然这个写也是对的。
438. 找到字符串中所有字母异位词 - 力扣(LeetCode)
class Solution {
public List<Integer> findSubstring(String s, String[] words){
List<Integer> ret = new ArrayList<Integer>();
Map<String ,Integer> hash1 = new HashMap<String,Integer>();
for (String str:words) hash1.put(str,hash1.getOrDefault(str,0)+1);
int len = words[0].length(),m = words.length;
for (int i=0;i<len;i++){
Map<String ,Integer> hash2 = new HashMap<String ,Integer>();
for (int left = i,right = i,count = 0;right+len<=s.length();right+=len){
//进窗口
String into = s.substring(right,right+len);
hash2.put(into,hash2.getOrDefault(into,0)+1);
if (hash2.get(into) <= hash1.getOrDefault(into,0)) count++;
//判断
if (right-left+1 > len *m)
{
//出窗口
String out = s.substring(left,left+len);
if (hash2.get(out) <= hash1.getOrDefault(out,0)){//如果是有效字符就count--
count--;
}
hash2.put(out,hash2.get(out)-1);//减去字符的hash2
left+=len;
}
//更新结果
if (count == m) ret.add(left);
}
}
return ret;
}
}