leetcode 30. 串联所有单词的子串 【时间击败 90.28%】 【内存击败 97.44%】
这道题让我从早做到晚-3-……
设len=words[0].length()。
一开始我按照words的顺序扩大区间,发现这样就依赖words的顺序。之后改成遍历s的所有长度为len*words.length的区间,超时,因为没有重复利用信息,只是单纯的暴力,每次i++移动一个单位是无法重复利用信息的。
要重复利用,只能每次移动len,这是能遍历所有情况的,以0~len-1为开头,每次移动len,就能遍历所有可能的情况。
话说hashmap是真的快,比数组遍历快得多
1 public List<Integer> findSubstring(String s, String[] words) { 2 if (s == null || words == null || words.length == 0 || s.length() == 0) return new ArrayList<>(); 3 4 int i, j, k, z; 5 HashMap<String, Integer> MAP = new HashMap<>(); 6 HashMap<String, Integer> map = new HashMap<>(); 7 ArrayList<Integer> al = new ArrayList<>(); 8 StringBuilder sb = new StringBuilder(s); 9 10 for (i = 0; i < words.length; i++) MAP.put(words[i], MAP.getOrDefault(words[i], 0) + 1); 11 12 int len = words[0].length(); 13 14 String tmp, t2; 15 for (k = 0; k < len; k++) { 16 map.clear(); 17 map.putAll(MAP); 18 19 OUT: 20 for (i = k, j = k; j + len <= s.length(); j += len) { 21 tmp = sb.substring(j, j + len); 22 if (!map.containsKey(tmp)) { 23 for (z = i; z < j; z += len) { 24 tmp = sb.substring(i, i + len); 25 map.put(tmp, map.get(tmp) + 1); 26 } 27 i = j + len; 28 continue; 29 } 30 map.put(tmp, map.get(tmp) - 1); 31 while (map.get(tmp) < 0 && i + len <= j) { 32 t2 = sb.substring(i, i + len); 33 34 map.put(t2, map.get(t2) + 1); 35 i += len; 36 } 37 for (Integer v : map.values()) if (v != 0) continue OUT; 38 al.add(i); 39 t2 = sb.substring(i, i + len); 40 map.put(t2, map.get(t2) + 1); 41 i += len; 42 } 43 } 44 return al; 45 }