问题描述
给定一个字符串和有相同长度的字符串组成的字符串数组(数组元素允许重复),要求找出字符串中所有由该数组的字符串(允许乱序)拼接而成的子字符串的起始下标。题目链接:**点我**
样例输入输出
输入:”barfoothefoobarman” [“foo”,”bar”]
输出:[0, 9]
解释: [“foo”,”bar”] 可以构成两个子字符串,”foobar” 和 “barfoo”,其中 “foobar” 出现在 “barfoothefoobarman” 的 9 ~ 14 (从 0 开始计算),”barfoo” 出现在 “barfoothefoobarman” 的 0 ~ 5 (从 0 开始计算)的位置,因此返回列表 [0, 9]
输入:”wordgoodgoodgoodbestword” [“word”,”good”,”best”,”word”]
输出:[]
解释: [“word”,”good”,”best”,”word”] 构成的所有的字符串均不是 “wordgoodgoodgoodbestword” 的子字符串,所以返回空的列表
问题解法
先用一个 map 将字符串数组中的字符串保存起来,然后遍历原始的字符串,截取固定长度(字符串数组中所有字符串的长度总和)的字符串,再从这个子字符串中依次取出每个 word 串,与 map 中保存的元素进行比较,如果不存在 map 中,说明截取的这个子字符串不满足条件,直接进入下一轮循环。当每个 word 串都存在 map 中并且每个 word 数量刚好与 map 中对应元素的数量相等时,说明截取的子字符串满足题目要求,此时记录截取的字符串的开始位置,继续下一轮循环。待循环结束时,返回每个下标组成的列表即可。代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| class Solution { public List<Integer> findSubstring(String s, String[] words) { List<Integer> result = new LinkedList<>(); if (s == null || s.length() == 0 || words == null || words.length == 0) { return result; } Map<String, Integer> wordMap = new HashMap<>(); for (String word : words) { Integer count = wordMap.getOrDefault(word, 0) + 1; wordMap.put(word, count); } int wordLength = words[0].length(); for (int i = 0; i < s.length(); i++) { if (i + wordLength * words.length > s.length()) { return result; } Map<String, Integer> workMapCopy = new HashMap<>(wordMap); for (int j = 0; j < words.length; j++) { String word = s.substring(i + j * wordLength, i + (j + 1) * wordLength); Integer count = workMapCopy.get(word); if (count == null) { break; } if (count == 1) { workMapCopy.remove(word); } else { workMapCopy.put(word, count - 1); } } if (workMapCopy.isEmpty()) { result.add(i); } } return result; } }
|