题目描述:
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) ins that is a concatenation of each word inwords 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).
最笨的办法就是枚举出来所有的子集,然后再从S中得到相应的index、不出意外超时了。
public List findSubstring(String s, String[] words) {
List list=new ArrayList();
for (int i = 0; i < words.length; i++) {
list.add(words[i]);
}
StringBuilder sb=new StringBuilder();
List wordList=new ArrayList();
List result=new ArrayList();
getAllSubString(list, sb, wordList);
for (int i = 0; i < wordList.size(); i++) {
int index;
if((index=s.indexOf(wordList.get(i)))!=-1){
result.add(index);
}
}
return result;
}
public void getAllSubString(List list,StringBuilder sb,List result){
if(list.size()==0)
result.add(sb.toString());
for(int i=0;i newList=new ArrayList(list);
newList.remove(list.get(i));
getAllSubString(newList, newSb, result);
}
}
后来用hashtable,创建map<string,integer>,int记录单词的个数,这样也超时了。此时的复杂度是O(m*n):
public List findSubstring(String s, String[] words) {
int n=words.length;
int len=words[0].length();
Map map=new HashMap();
List result=new ArrayList();
for(int i=0;i0){
map.put(str, map.get(str) - 1);
cnt++;
start += len;
if (start + len > s.length()) break; //注意越界
str = s.substring(start, start + len);
}
if (cnt == n) {
result.add(i);
}
if(cnt>0){
map.clear();
for(int j=0;j
后来参考了别人的做法,实在是巧妙。
public List findSubstring(String S, String[] L) {
List ret = new ArrayList();
int slen = S.length(), llen = L.length;
if (slen <= 0 || llen <= 0)
return ret;
int wlen = L[0].length();
// get the words' map
HashMap words = new HashMap();
for (String str : L) {
if (words.containsKey(str)) {
words.put(str, words.get(str) + 1);
} else {
words.put(str, 1);
}
}
for (int i = 0; i < wlen; ++i) {
int left = i, count = 0;
HashMap tmap = new HashMap();
for (int j = i; j <= slen - wlen; j += wlen) {
String str = S.substring(j, j + wlen);
if (words.containsKey(str)) {
if (tmap.containsKey(str)) {
tmap.put(str, tmap.get(str) + 1);
} else {
tmap.put(str, 1);
}
if (tmap.get(str) <= words.get(str)) {
count++;
} else {
// too many words, push the 'left' forward
while (tmap.get(str) > words.get(str)) {
String tmps = S.substring(left, left + wlen);
tmap.put(tmps, tmap.get(tmps) - 1);
if (tmap.get(tmps) < words.get(tmps)) {
// if affect the count
count--;
}
left += wlen;
}
}
// get the answer
if (count == llen) {
ret.add(left);
// it's better to push forward once
String tmps = S.substring(left, left + wlen);
tmap.put(tmps, tmap.get(tmps) - 1);
count--;
left += wlen;
}
} else {
// not any match word
tmap.clear();
count = 0;
left = j + wlen;
}
}
}
return ret;
}