(Java)LeetCode-30. Substring with Concatenation of All Words

来源:互联网 发布:lol职业选手训练软件 编辑:程序博客网 时间:2024/04/30 06:34

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 timeHashMap<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);}}

哎,就这样吧~无聊的题

0 0