You are given a string, s, and a list of words, words, that are all of the same length. Find all starting indices of substring(s) in s that is a concatenation of each word in words exactly once and without any intervening characters.
For example, given:
s: "barfoothefoobarman"
words: ["foo", "bar"]
You should return the indices: [0,9]
.
(order does not matter).
思路:思路是使用滑动窗口来解决问题,首先要找到起始位置,因为题目例如“barfoothefoobarman”,["foo","bar"],要查找的字符串长度为3,那么假设从开头开始找,我们就按顺序找bar,foo,the,foo,bar,man,然后在从第二个开始找,arf,oot,hef,oob,arm,再从三个开始找,rfo,oth,efo,oba,rma,然后从第四个开始找,这是我们就会发现其实已经重复了,也就是从第一个开始找,已经包含了从第四个开始找的内容,所以我们会在代码中看到,最外层循环是3
然后每次循环是这样的,我们从起始位置,每次获取三个字符作为字符串,并且检验是否是我们要找的字符串,如果是,修改记录(说明找到了一个);如果不是,就要移动起始位置
就算我们找到了要找的一个字符串,它也可能是多余的,例如我们之前已经找到了foo,但是下一个还是foo,超出的我们要找的foo数目,这时就要移动其实位置,直到记录中的foo数目小于或等于要找的数目,再重新设置其实位置
当我们找齐了所以字符串,保存当前起始位置,然后再去除窗口的第一个记录,接着继续向右查找
public class Solution { public List<Integer> findSubstring(String s, String[] words) { List<Integer> result = new ArrayList<Integer>(); if(s==null || s.length()==0 || words==null || words.length==0) return result; Map<String,Integer> map = new HashMap<String,Integer>(); for(int i=0;i<words.length;i++){//初始化map if(map.containsKey(words[i])){ map.put(words[i],map.get(words[i])+1); }else{ map.put(words[i],1); } } int word_size = words[0].length(); for(int i=0;i<word_size;i++){//注意,这里循环字符串长度即可 Map<String,Integer> findmap = new HashMap<String,Integer>();//用于记录当前字符串收集情况 int count = 0;//当前收集个数 int start = i;//当前起始index for(int j=i;j<=s.length()-word_size;j+=word_size){//从当前起始index开始到能容纳一个字符串的位置,j表示字符串的起始坐标 String word = s.substring(j, j+word_size);//获取当前字符串 if(map.containsKey(word)){ if(!findmap.containsKey(word)){ findmap.put(word, 1); }else{ findmap.put(word, findmap.get(word)+1); } if(findmap.get(word)>map.get(word)){//滑动窗口 while(findmap.get(word)>map.get(word)){//移动窗口直到消除多出来的字符串 String str = s.substring(start, start+word_size); if(findmap.containsKey(str)){ findmap.put(str, findmap.get(str)-1); if(findmap.get(str)<map.get(str)) count--; } start += word_size;//重定位起始位置 } }else{ count++; } if(count==words.length){//找齐 result.add(start); String temp = s.substring(start,start+word_size); if(findmap.containsKey(temp))//去除第一个 findmap.put(temp,findmap.get(temp)-1); count--;//数目减少1 start += word_size;//重定位起始位置 } }else{//如果不是要找的字符串 count = 0; start = j+word_size;//重定位起始位置 findmap.clear(); } } } //System.err.println(result); return result; } }