|
1 | 1 | package g0001_0100.s0030_substring_with_concatenation_of_all_words |
2 | 2 |
|
3 | 3 | // #Hard #String #Hash_Table #Sliding_Window #Top_Interview_150_Sliding_Window |
4 | | -// #2023_07_03_Time_182_ms_(100.00%)_Space_37.9_MB_(100.00%) |
| 4 | +// #2025_03_04_Time_14_ms_(98.62%)_Space_39.70_MB_(91.72%) |
5 | 5 |
|
6 | 6 | class Solution { |
7 | 7 | fun findSubstring(s: String, words: Array<String>): List<Int> { |
8 | | - val indices: MutableList<Int> = ArrayList() |
9 | | - if (words.size == 0) { |
10 | | - return indices |
| 8 | + val ans: MutableList<Int> = ArrayList<Int>() |
| 9 | + val n1 = words[0].length |
| 10 | + val n2 = s.length |
| 11 | + val map1: MutableMap<String, Int> = HashMap<String, Int>() |
| 12 | + for (ch in words) { |
| 13 | + map1.put(ch, map1.getOrDefault(ch, 0) + 1) |
11 | 14 | } |
12 | | - // Put each word into a HashMap and calculate word frequency |
13 | | - val wordMap: MutableMap<String, Int> = HashMap() |
14 | | - for (word in words) { |
15 | | - wordMap[word] = wordMap.getOrDefault(word, 0) + 1 |
16 | | - } |
17 | | - val wordLength = words[0].length |
18 | | - val window = words.size * wordLength |
19 | | - for (i in 0 until wordLength) { |
20 | | - // move a word's length each time |
| 15 | + for (i in 0..<n1) { |
| 16 | + var left = i |
21 | 17 | var j = i |
22 | | - while (j + window <= s.length) { |
23 | | - // get the subStr |
24 | | - val subStr = s.substring(j, j + window) |
25 | | - val map: MutableMap<String, Int> = HashMap() |
26 | | - // start from the last word |
27 | | - for (k in words.indices.reversed()) { |
28 | | - // get the word from subStr |
29 | | - val word = subStr.substring(k * wordLength, (k + 1) * wordLength) |
30 | | - val count = map.getOrDefault(word, 0) + 1 |
31 | | - // if the num of the word is greater than wordMap's, move (k * wordLength) and |
32 | | - // break |
33 | | - if (count > wordMap.getOrDefault(word, 0)) { |
34 | | - j = j + k * wordLength |
35 | | - break |
36 | | - } else if (k == 0) { |
37 | | - indices.add(j) |
38 | | - } else { |
39 | | - map[word] = count |
| 18 | + var c = 0 |
| 19 | + val map2: MutableMap<String, Int> = HashMap<String, Int>() |
| 20 | + while (j + n1 <= n2) { |
| 21 | + val word1 = s.substring(j, j + n1) |
| 22 | + j += n1 |
| 23 | + if (map1.containsKey(word1)) { |
| 24 | + map2.put(word1, map2.getOrDefault(word1, 0) + 1) |
| 25 | + c++ |
| 26 | + while (map2[word1]!! > map1[word1]!!) { |
| 27 | + val word2 = s.substring(left, left + n1) |
| 28 | + map2.put(word2, map2[word2]!! - 1) |
| 29 | + left += n1 |
| 30 | + c-- |
| 31 | + } |
| 32 | + if (c == words.size) { |
| 33 | + ans.add(left) |
40 | 34 | } |
| 35 | + } else { |
| 36 | + map2.clear() |
| 37 | + c = 0 |
| 38 | + left = j |
41 | 39 | } |
42 | | - j = j + wordLength |
43 | 40 | } |
44 | 41 | } |
45 | | - return indices |
| 42 | + return ans |
46 | 43 | } |
47 | 44 | } |
0 commit comments