题目:力扣https://leetcode-cn.com/problems/substring-with-concatenation-of-all-words/
class Solution {
public List<Integer> findSubstring(String s, String[] words) {
List<String> baseList = Arrays.asList(words);//将字符出串数组转化为集合
List<String> wordList;//提前声明,备用
List<Integer> res = new ArrayList<>();//用于存答案的集合
int len = words[0].length();//word的长度,题目规定了各个word都相等
for(int cur=0;cur<=s.length()-len*words.length;cur++){
//s.length()-len*words.length//当s.leng()的长度比word的总长度要小的时候即表示已经到尽头
boolean flag = true;//记录匹配状态
wordList = new ArrayList<>(baseList);//
for(int i=0;i<words.length;i++){
if(!flag){
continue;
}
flag = wordList.remove(s.substring(cur+(i*len) , cur+((i+1)*len)));
//移除成功给返回true,移除失败返回false。即进行了比对,有避免了重复,妙哉妙哉
}
if(flag){//flag的值为true的时候表示匹配成功,记录下起初位置的下标
res.add(cur);
}
}
return res;
}
}
思路:这一题我也是学习了别的大佬的思路,关键在于巧妙地使用remove(),用remove()一个方法同时做到判别与去重的两个作用。
1.准备工作。将words数组转换成集合,方便后续操作;wordList是后续需要用到的临时集合,在此处先声明;res是用于存储最后答案的集合。因为题目规定,words中的每个字符串的长度是相等的,即可以用word[0]的长度代表所有words数组中字符串的长度,并将其存储在len变量中。
List<String> baseList = Arrays.asList(words);//将字符出串数组转化为集合
List<String> wordList;//提前声明,备用
List<Integer> res = new ArrayList<>();//用于存答案的集合
int len = words[0].length();//word的长度,题目规定了各个word都相等
2.cur是表示原字符串s当前的位置,当cur到达一定的位置即代表长度已经不够,不可能匹配成功了。(这个临界点是:s.length()-len*words.length)声明一个flag用于记录当前匹配状态的,将baseList赋值给wordList集合(因为后面需要对集合进行remove操作,因为不确保一次循环即可匹配成功,所以需要一个临时的集合来做baseList的替身,让wordList来做remove操作。这样就算第一次循环没有匹配成功,但仍然保证了baseList的完整性,在下一次循环中可以重新赋值给wordList,再一次进行匹配。)
for(int cur=0;cur<=s.length()-len*words.length;cur++){
//s.length()-len*words.length//当s.leng()的长度比word的总长度要小的时候即表示已经到尽头
boolean flag = true;//记录匹配状态
wordList = new ArrayList<>(baseList);//
//....
}
3.i表示单词word的个数。if(!flag){...}表示如果,flag为false表示已经匹配失败了,则不需要进行下面进一步的匹配了,需要返回上一层改变原字符串s的起始位置;若flag为true则表示暂时匹配成功了,可以进一步的匹配。flag = wordList.remove(s.substring(cur+(i*len) , cur+((i+1)*len)));这一句是这份代码最精髓的一句代码,它的作用是让通过 原字符串s中特定位置的一段 与 单词word集合 的比对判断是否匹配成功。若删除成功表示匹配成功,会返回true值给flag同时把该单词去除,达到去重的目的,非常非常的巧妙。
for(int i=0;i<words.length;i++){
if(!flag){
continue;
}
flag = wordList.remove(s.substring(cur+(i*len) , cur+((i+1)*len)));
//移除成功给返回true,移除失败返回false。即进行了比对,有避免了重复,妙哉妙哉
}
8.剩下只需要根据flag的判断上面是否匹配成功,若成功则将原字符串s的起始位置cur记录再res集合中,若不成功则移动原字符串s的起始位置cur,进行新一轮的匹配。
if(flag){//flag的值为true的时候表示匹配成功,记录下起初位置的下标
res.add(cur);
}
9.最后的最后,只需要返回装着答案的集合res即可。
return res;