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).
这道题Hard模式,比较复杂,又没有用到很经典的算法,卡在这道题很长时间了。
首先比较直观的解法
package datastru;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Solution {
public List<Integer> findSubstring(String s, String[] words) {
Map<String, Integer> map = new HashMap<String, Integer>();
for(String word : words){
if(map.containsKey(word)){
map.put(word, map.get(word)+1);
}else{
map.put(word, 1);
}
}
List<Integer> result = new ArrayList<Integer>();
int len = words[0].length();
int cal_len = s.length() - words.length * len;
for(int i = 0; i <= cal_len; i++){
Map<String, Integer> copy_map = new HashMap<String, Integer>(map);
int temp = i;
String sub_s = s.substring(temp,temp+len);
while(copy_map.containsKey(sub_s)){
if(copy_map.get(sub_s) == 1){
copy_map.remove(sub_s);
}else{
copy_map.put(sub_s, copy_map.get(sub_s)-1);
}
temp = temp + len;
if(temp+len<=s.length()){
sub_s = s.substring(temp,temp+len);
}else{
break;
}
}
if(copy_map.isEmpty()){
result.add(i);
}
}
return result;
}
public static void main(String[] args){
Solution sol = new Solution();
String s = "wordgoodgoodgoodbestword";
String[] words = {"word","good","best","good"};
List<Integer> list= sol.findSubstring(s, words);
System.out.println(list);
}
}
这样做超时了,因为有很多重复的检查,下面这种做法是在discuss里面看到的,去掉了这种重复,厉害厉害。我就没有自己写了,直接复制如下。
idea is use hashmap and slide window.
the single word's length is k , than we have k kinds of windows.
for each kind of window, we slide it right k length
if find a new word not belongs to dictionary, then put start at it's right and clean the hashmap COPY
public class Solution {
public List<Integer> findSubstring(String s, String[] L) {
List<Integer> list = new ArrayList<Integer>();
if(s==null|| s==""||L==null||L[0].length()==0)
return list;
HashMap<String, Integer> map = new HashMap<String ,Integer>();
int len=L[0].length();
int k = len;
int count = L.length;
for (String tmp : L) {
if(!map.containsKey(tmp)) {
map.put(tmp, 1);
}else
map.put(tmp,map.get(tmp)+1);
}
String curr = "";
int start = 0;
int x = 0;
for (int i = 0; i <k; i++) { // there are k kind of slide window, and slide right k each time
HashMap<String , Integer> copy = new HashMap<>();
start = i;
for(int j =i; j+k<=s.length(); j = j + k ){ // slide window, the window's length is k*count
curr = s.substring(j,j+k);
if(map.containsKey(curr)){ //curr belongs to dictionary
addright(copy,curr);
if(j+k - start > k*count){ // window size exceed k*count
removeleft(copy, s.substring(start,start+k));
start = start + k;
}
if(j+k-start == k*count && copy.equals(map))
list.add(start);
}else{ // dictionary don't include curr, skip it
copy.clear();
start = j + k;
}
}
}
return list;
}
public void addright(HashMap<String,Integer> copy, String curr){
if(copy.containsKey(curr)){ // curr l in copy
copy.put(curr,copy.get(curr)+1);
}else{ // curr do not exist in copy, but it belongs to dictionary
copy.put(curr,1);
}
}
public void removeleft(HashMap<String,Integer> copy, String curr){
int x = copy.get(curr);
if(x==1) copy.remove(curr);
else copy.put(curr,x-1);
}
}
哎,就这样吧~无聊的题