算法17.0
30. 串联所有单词的子串 - 力扣(LeetCode)
解法1:暴力解法
解法2:算法14.0的算法原理+细节处理
这道题目的核心是算法14.0
算法14.0里面有很多细节问题 下面开始尝试自己的总结
// char[ ] s = ss.toCharArray( ) ; 将ss字符串转化为s字符数组
//for(char ch:p ) hash[ch-'a']++; 这个是增强for循环 放括号里面是将字符ch转换为0--25的下标到hash1里面
//if(++ hash2[in-'a'] <= hash1[ in-'a']) count++; 先给hash2中对应的下标的值加1 统计当前字符in出现的次数 再参与后续的比较
//算法14.0的关键是更新结果的部分
check(hash1,hash2) 这样的解决办法优化为利用变量count来统计窗口中"有效字符”的个数
关于有效字符的理解:
如果这个字符的数量小于p哈希表里面的字符 说明这个字符是可以抵消p哈希表里面的有效字符
如果这个字符的数量大于p哈希表里面的字符 这个是无效字符
一遍往窗口里面添加元素 一边维护count
后续删除窗口里面的元素也需要维护count
(如果此时删字符的时候 如果出现的次数已经大于p哈希表里面的对应字符 删掉
同时要注意count表示的是有效字符的数量)
算法原理:

细节问题:
1.for(String str :words)hash1.put(str,hash1,getOrDefault(str,0)+1);
将words字符串数组的东西放到hash表1中 如果是str字符串 就返回这个str这个字符串+1
如果不是str字符串 就规定为0+1 然后扔到哈希表里面
简单描述:传入str字符串 如果这个转入的字符串str已经存在哈希表里面 返回里面的值+1 如果不存在 返回0 然后加1(表示出现一次)
AI辅助理解:

2.right的极限位置 理解right+len<s.length( ) ;

3. if(hash.get(in)<=hash1.get(in)) count++;
第一个哈希表里面不一定有那个字符啊 还没有见到第一次 是不是报错了
if(hash.get(in)<=hash1.getOrDefault(in,0)) count++;
如果存在 返回里面的值 如果不存在 返回0 0绝对是小于hash.get(in)的
4.代码的注释部分
下面是题目、效果图和代码:


class Solution {public List<Integer> findSubstring(String s, String[] words) {List<Integer> ret = new ArrayList<Integer>();Map<String,Integer> hash1 = new HashMap<String,Integer>(); //保存字典中所有单词的信息 String是存储这个字符 Integer是统计出现的次数for(String str: words) hash1.put(str,hash1.getOrDefault(str,0)+1);//统计字典里面的字符 以及各个字符出现的次数int len = words[0].length(), m = words.length;//len是获取数组第一个单词的长度 m是获取数组words的单词数量for(int i = 0; i<len;i++){ //执行次数//因为left指针的位置也在发生变化 所以还需要一个循环 left和right都是从i开始 不能从0开始 如果是从0开始 执行结果就一样了 算法14.0里 面的东西是统计有效字符的个数 这里的count是统计字符串的个数 right每次向后移动是len步//所以是right+=len right是要让right所指的单词丢到里面 right有极限位置(图片里面的绿色条 蓝色条) right的极限位置是right+ken的长度Map<String,Integer> hash2 = new HashMap<String,Integer>(); //用来保存窗口内所有单词的频次for(int left = i,right = i,count = 0; right+len<=s.length() ;right += len){//进窗口+维护 count 就是让right所指的单词进入窗口String in = s.substring(right,right+len); //这个时候in就是存的要进的字符串hash2.put(in,hash2.getOrDefault(in,0)+1);//如果是存在的话 是之前的值+1if(hash2.get(in) <= hash1.getOrDefault(in,0)) count++;//判断if (right-left+1>len * m){//出窗口+维护countString out =s.substring(left,left + len);if(hash2.get(out)<=hash1.getOrDefault(out,0)) count--; //出窗口之前要判断hash2.put(out,hash2.get(out)-1);left+=len;}//更新结果 if(count == m) ret.add(left);}}return ret;}
}
//xiyu251023&1#2*7 第一道“困难”题
