Q30 串联所有单词的子串
题目描述
给定一个字符串 s
和一些 长度相同 的单词 words
。找出 s
中恰好可以由 words
中所有单词串联形成的子串的起始位置。
注意子串要与 words
中的单词完全匹配,中间不能有其他字符,不必考虑words中单词的顺序,words中可能包含相同的单词。
解题思路
如果子串是恰好由words中所有单词串联而成,则说明子串和words数组的构成成分一样(即words数组中包含n个单词hello,则子串中也包含n个hello)。
通过words中的单词及其出现次数作为key-value构建一个Map,再通过依次截取的子串中的单词及其出现次数作为key-value构建一个Map,通过比较两个Map是否相等即可判断该子串是否恰好由words中所有单词串联而成。
Java代码实现
package com.peng.leetcode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
* 给定一个字符串 s 和一些 长度相同 的单词 words 。找出 s 中恰好可以由 words 中所有单词串联形成的子串的起始位置。
*/
public class Q30 {
public static List<Integer> findSubstring(String s, String[] words) {
List<Integer> result = new ArrayList<>();
//处理非法输入
if(s == null || s.length() == 0 || words == null || words.length == 0) {
return result;
}
//初始化作为参照的Map
HashMap<String, Integer> mapWords = new HashMap<>();
for(int i = 0; i < words.length; i++) {
mapWords.put(words[i], mapWords.getOrDefault(words[i], 0) + 1);
}
int wordsLength = words.length * words[0].length();
for(int i = 0; i <= s.length() - wordsLength; i++) {
HashMap<String, Integer> mapS = new HashMap<>(); //待比较的Map
for(int j = i; j <= i + wordsLength - words[0].length(); j += words[0].length()) {
String str = s.substring(j, j + words[0].length());
mapS.put(str, mapS.getOrDefault(str, 0) + 1);
}
if(mapS.equals(mapWords)) {
result.add(i);
}
}
return result;
}
}