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).
思路:暴力解法:就是 i 扫描到 s.length() - words[0].length * words.length; 然后用hashmap进行统计一次,然后每次走的时候,就进行更新,满足条件就加到list中。这题其实最规范的应该是当hashmap清空的时候就加list。
public class Solution {
public List<Integer> findSubstring(String s, String[] words) {
List<Integer> list = new ArrayList<Integer>();
int wordlen = words[0].length();
int totallen = wordlen*words.length;
if(s == null || s.length() < totallen) return list;
HashMap<String,Integer> hashmap = new HashMap<String, Integer>();
for(String str: words) {
if(hashmap.containsKey(str)) {
hashmap.put(str, hashmap.get(str)+1);
} else {
hashmap.put(str,1);
}
}
for(int i=0; i<=(s.length() - totallen); i++){
HashMap<String, Integer> newmap = new HashMap<String,Integer>(hashmap);
int start = i;
while(start<=s.length()-wordlen){
String str = s.substring(start, start+wordlen);
if(newmap.containsKey(str) && newmap.get(str)>0){
start +=wordlen;
if(newmap.get(str) == 1){
newmap.remove(str);
} else {
newmap.put(str, newmap.get(str)-1);
}
} else {
break;
}
if(newmap.size() ==0){
list.add(i);
}
}
}
return list;
}
}
更好的窗口法:就是起点是word length以内为起点,然后j每次移动wordlen的距离,这样可以包含所有的wordlen的情况,那么j往后移动,start相应的来滑动,并更新当前的curDict和count,相当于滑动word len个 i,j窗口,所以最后复杂度是O(wordlen*n) = O(n)的。懂得了滑动窗口,这题应该不难,只是每次移动wordlen个位置,而且要需要移动wordlen次窗口运算,想到这点,比较难。另外,start怎么移动,这个也是个考点。start移动法则就是:如果当count word 大于了应有的次数,那么start往右边移动。并且update字典频率和count。
public class Solution {
public List<Integer> findSubstring(String s, String[] words) {
ArrayList<Integer> list = new ArrayList<Integer>();
if(s == null || words == null || s.length() == 0 || words.length == 0) return list;
HashMap<String, Integer> hashmap = new HashMap<String, Integer>();
for(int i=0; i<words.length; i++) {
String str = words[i];
Integer k = hashmap.get(str);
if(k == null) {
hashmap.put(str, 1);
} else {
hashmap.put(str, k+1);
}
}
int wordlen = words[0].length();
for(int i=0; i<wordlen; i++){
int start = i;
HashMap<String, Integer> curDict = new HashMap<String, Integer>();
int len = 0;
for(int j=i; j<=s.length()-wordlen; j+=wordlen){
String str = s.substring(j, j+wordlen);
if(!hashmap.containsKey(str)){
len = 0;
curDict.clear();
start = j+wordlen;
} else { // hashmap.containsKey(str);
if(curDict.containsKey(str)){
curDict.put(str, curDict.get(str)+1);
} else {
curDict.put(str, 1);
}
if(curDict.get(str)<= hashmap.get(str)){
len++;
} else { // curDict.get(str) > hashmap.get(str);
while(curDict.get(str) > hashmap.get(str)){ // 因为前面已经加进去了,现在要移动start指针,来update;
String temp = s.substring(start, start+wordlen);
if(curDict.containsKey(temp)){
curDict.put(temp, curDict.get(temp)-1);
}
if(curDict.get(temp) < hashmap.get(temp)){
len--;
}
start += wordlen;
}
}
if(len == words.length){
list.add(start);
String temp = s.substring(start, start+wordlen);
if(curDict.containsKey(temp)){
curDict.put(temp, curDict.get(temp)-1);
}
if(curDict.get(temp) < hashmap.get(temp)){
len--;
}
start += wordlen;
}
}
}
}
return list;
}
}