目錄
- 1.題目
- 2.答案
- 3.提交結果截圖
- 4.圖解
鏈接: 串聯所有單詞的子串
1.題目
給定一個字符串 s
和一個字符串數組 words
。 words
中所有字符串 長度相同。
s
中的 串聯子串 是指一個包含 words
中所有字符串以任意順序排列連接起來的子串。
- 例如,如果
words = ["ab","cd","ef"]
, 那么"abcdef"
,"abefcd"
,"cdabef"
,"cdefab"
,"efabcd"
, 和"efcdab"
都是串聯子串。"acdbef"
不是串聯子串,因為他不是任何words
排列的連接。
返回所有串聯子串在 s
中的開始索引。你可以以 任意順序 返回答案。
示例 1:
輸入:s = "barfoothefoobarman", words = ["foo","bar"]
輸出:[0,9]
解釋:因為 words.length == 2 同時 words[i].length == 3,連接的子字符串的長度必須為 6。
子串 "barfoo" 開始位置是 0。它是 words 中以 ["bar","foo"] 順序排列的連接。
子串 "foobar" 開始位置是 9。它是 words 中以 ["foo","bar"] 順序排列的連接。
輸出順序無關緊要。返回 [9,0] 也是可以的。
示例 2:
輸入:s = "wordgoodgoodgoodbestword", words = ["word","good","best","word"]
輸出:[]
解釋:因為 words.length == 4 并且 words[i].length == 4,所以串聯子串的長度必須為 16。
s 中沒有子串長度為 16 并且等于 words 的任何順序排列的連接。
所以我們返回一個空數組。
示例 3:
輸入:s = "barfoofoobarthefoobarman", words = ["bar","foo","the"]
輸出:[6,9,12]
解釋:因為 words.length == 3 并且 words[i].length == 3,所以串聯子串的長度必須為 9。
子串 "foobarthe" 開始位置是 6。它是 words 中以 ["foo","bar","the"] 順序排列的連接。
子串 "barthefoo" 開始位置是 9。它是 words 中以 ["bar","the","foo"] 順序排列的連接。
子串 "thefoobar" 開始位置是 12。它是 words 中以 ["the","foo","bar"] 順序排列的連接。
提示:
1 <= s.length <= 10^4
1 <= words.length <= 5000
1 <= words[i].length <= 30
words[i]
和s
由小寫英文字母組成
2.答案
class Solution {public List<Integer> findSubstring(String s, String[] words) {List<Integer> result = new ArrayList<>();int wordLength = words[0].length();int wordCount = words.length;for (int i = 0; i < wordLength; i++) {// 超出長度if (i + wordCount * wordLength > s.length()) {break;}// 初始化窗口Map<String, Integer> map = new HashMap<>();for (int j = 0; j < wordCount; j++) {String word = s.substring(i + j * wordLength, i + (j + 1) * wordLength);map.put(word, map.getOrDefault(word, 0) + 1);}// 篩掉原單詞數組for (String word : words) {map.put(word, map.getOrDefault(word, 0) - 1);if (map.get(word) == 0) {map.remove(word);}}// 滑動窗口for (int j = 0; i + j + wordCount * wordLength <= s.length(); j+=wordLength) {if (j != 0) {String addWord = s.substring(i + j + wordLength * (wordCount - 1), i + j + wordLength * wordCount);map.put(addWord, map.getOrDefault(addWord, 0) + 1);if (map.get(addWord) == 0) {map.remove(addWord);}String delWord = s.substring(i + j - wordLength, i + j);map.put(delWord, map.getOrDefault(delWord, 0) - 1);if (map.get(delWord) == 0) {map.remove(delWord);}}if (map.size() == 0) {result.add(i + j);}}}return result;}
}
3.提交結果截圖
4.圖解
以如下測試用例舉例說明:
輸入:s = "barfoothefoobarman", words = ["foo","bar"]
輸出:[0,9]
首先,可以將字符串 s
按照單詞長度進行劃分,通過開頭跳過字符長度的方式,可以分為以下三種劃分方式。
以劃分方式1舉例,可以將所有單詞總長度(單詞數
* 單詞長度
)來作為一個窗口,從左往右滑動。
最終得到的 index=0
和 index=9
就是我們的結果了。
整理完畢,完結撒花~ 🌻