题目描述:
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;i
0){ 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; }