方法一:
两个 HashMap 来解决。首先,我们把所有的单词存到 HashMap 里,key 直接存单词,value 存单词出现的个数(。然后扫描子串的单词,如果当前扫描的单词在之前的 HashMap 中,就把该单词存到新的 HashMap 中,并判断新的 HashMap 中该单词的 value 是不是大于之前的 HashMap 该单词的 value ,如果大了,就代表该子串不是我们要找的,接着判断下一个子串就可以了。如果不大于,那么我们接着判断下一个单词的情况。子串扫描结束,如果子串的全部单词都符合,那么该子串就是我们找的其中一个。看下具体的例子。
看下图,我们把 words 存到一个 HashMap 中。
然后遍历子串的每个单词。
第一个单词在 HashMap1 中,然后我们把 foo 存到 HashMap2 中。并且比较此时 foo 的 value 和 HashMap1 中 foo 的 value,1 < 2,所以我们继续扫描。
第二个单词也在 HashMap1 中,然后把 foo 存到 HashMap2 中,因为之前已经存过了,所以更新它的 value 为 2 ,然后继续比较此时 foo 的 value 和 HashMap1 中 foo 的 value,2 <= 2,所以继续扫描下一个单词。
第三个单词也在 HashMap1 中,然后把 foo 存到 HashMap2 中,因为之前已经存过了,所以更新它的 value 为 3,然后继续比较此时 foo 的 value 和 HashMap1 中 foo 的 value,3 > 2,所以表明该字符串不符合。然后判断下个子串就好了。
下面是AC代码,87ms.
class Solution {
public List<Integer> findSubstring(String s, String[] words) {
List<Integer> list=new ArrayList();
if(s==null||s.length()==0||words==null||words.length==0)
return list;
Map<String,Integer> wordMap=new HashMap();
for(String word : words){
if(!wordMap.containsKey(word))
wordMap.put(word,1);
else
wordMap.put(word,wordMap.get(word)+1);
}
int slen=s.length(),arraylen=words.length,wordlen=words[0].length();
for(int i=0;i<slen-arraylen*wordlen+1;i++){
Map<String,Integer> map=new HashMap();
int num=0;
while(num<arraylen){
String word=s.substring(i+num*wordlen,i+(num+1)*wordlen);
if(wordMap.containsKey(word)){
int value=map.getOrDefault(word,0);
map.put(word,value+1);
if(wordMap.get(word)<map.get(word))
break;
}else
break;
num++;
}
if(num==arraylen)
list.add(i);
}
return list;
}
}
方法二:
对上面的解法进行优化,同样用两个HashMap存储,这个优化方案是利用了给定的Word都是等长的
虽然该方案不具备普适性,但是对于这道题来说,这个优化是可行的,可以提高效率。
具体做法是,循环利用原来的匹配结果来跳过那些没必要匹配的值。
优化难点在于对三种情形下left值以及map和num值的更新。
详细理解:详细图解
AC代码如下: 13ms beats 96.6%
class Solution {
public List<Integer> findSubstring(String s, String[] words) {
List<Integer> list=new ArrayList();
if(s==null||s.length()==0||words==null||words.length==0)
return list;
Map<String,Integer> wordMap=new HashMap();
for(String word : words){
if(!wordMap.containsKey(word))
wordMap.put(word,1);
else
wordMap.put(word,wordMap.get(word)+1);
}
int slen=s.length(),arraylen=words.length,wordlen=words[0].length();
for(int i=0;i<wordlen;i++){
Map<String,Integer> map=new HashMap();
int num=0;
for(int left=i;left<slen-arraylen*wordlen+1;left=left+wordlen){
boolean remove=false;
while(num<arraylen){
String word=s.substring(left+num*wordlen,left+(num+1)*wordlen);
if(wordMap.containsKey(word)){
int value=map.getOrDefault(word,0);
map.put(word,value+1);
if(map.get(word)>wordMap.get(word)){
remove=true;
int count=0;
while(map.get(word)>wordMap.get(word)){
String more=s.substring(left+count*wordlen,left+(count+1)*wordlen);
map.put(more,map.get(more)-1);
count++;
}
num=num-count+1;
left=left+(count-1)*wordlen;
break;
}
}else{
map.clear();
left=left+num*wordlen;
num=0;
break;
}
num++;
}
if(num==arraylen)
list.add(left);
if(num==arraylen&&!remove){
String w=s.substring(left,left+wordlen);
map.put(w,map.get(w)-1);
num--;
}
}
}
return list;
}
}
致谢参考: 链接