30. Substring with Concatenation of All Words (JAVA)
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.
Example 1:
Input:
s = "barfoothefoobarman",
words = ["foo","bar"]
Output: [0,9]
Explanation: Substrings starting at index 0 and 9 are "barfoor" and "foobar" respectively.
The output order does not matter, returning [9,0] is fine too.
Example 2:
Input:
s = "wordgoodgoodgoodbestword",
words = ["word","good","best","word"]
Output: []
class Solution { public List<Integer> findSubstring(String s, String[] words) { List<Integer> ret = new ArrayList<>(); if(words==null || words.length==0) return ret; int start; //start index of s int cur; //current index of s Map<String, Integer> wordCnt= new HashMap<String, Integer>(); //count of each word Map<String, Integer> strCnt= new HashMap<String, Integer>(); //count of each word while traversing string String w; String w_to_del; int startIndex; int cnt; int len = words[0].length(); int strLen = words.length * len; //initialize map for(String str: words){ wordCnt.put(str,wordCnt.getOrDefault(str,0)+1); } for(int j = 0; j < len; j++){ //word可能会出现在s的任意位置,而非仅仅0,len,2*len...的位置 startIndex = j; strCnt.clear(); for(int i = j; i <= s.length()-len; i+=len){ w = s.substring(i,i+len); if(wordCnt.containsKey(w)){ //word in words strCnt.put(w, strCnt.getOrDefault(w,0)+1); //number of word in string is more than that in words array, move right startIndex while(strCnt.get(w) > wordCnt.get(w)){ w_to_del = s.substring(startIndex,startIndex+len); strCnt.put(w_to_del,strCnt.get(w_to_del)-1); startIndex += len; } //find a match if(i + len - startIndex == strLen){ ret.add(startIndex); //start to find another match from startIndex+len w_to_del = s.substring(startIndex,startIndex+len); strCnt.put(w_to_del,strCnt.get(w_to_del)-1); startIndex += len; } } else{ //word not in words startIndex = i+len; strCnt.clear(); } } } return ret; } }
时间复杂度:通过window的方式,在每个word的起始位置,只要遍历一遍s,就能完成查询。一共有size =words.length个起始位置,所以时间复杂度是O(n*size),其中n为s的长度,在s很长的时候,可以认为size是可忽略的常量,时间复杂度为O(n)。