题目描述:
您将获得一个字符串 S 和一个单词列表 L,它们的长度都相同。
找到 S 中子串的所有起始索引,它是 L 中每个单词的串联,只有一次,没有任何插入字符。
例如,给定:
S:“barfoothefoobarman”
L:[“foo”,“bar”]
你应该返回索引:[0,9]。
(顺序无所谓)。
解题思路:
- 理解题意最重要,题目的意思就是说,找到 S 中的字串 sunString,使其包含所有的 L 中的字符串,其中 L 中的字符串顺序无所谓(看到这里,你首先应该想到的是 HashMap )
- 对于这题,我首先想到的是将 L 中的字符串利用全排列组成一整个字符串,然后再在 S 中找
- 然后发现这样工作量特别大
- 这里采用遍历 S 字符串,截取固定长度的方法,具体的思路如下
- 将 L 中的字符串用 hashmap 来存储,字符串作为键,次数作为值
- 因为这里 L 中的字符串长度固定,按顺序从 S 中取出固定的长度字符串,并判断是否存在与 hashmap 中,这里同时也建立一个临时 hashmap,取名为 temp, 用来防止单个字符串多次出现的情况
代码如下:
public ArrayList<Integer> findSubstring(String S, String[] L) {
ArrayList<Integer> list = new ArrayList<>();
if(S.isEmpty() || L == null || L.length == 0)
return list;
int n = L.length;
int size = L[0].length();
HashMap<String, Integer> wordCnt = new HashMap<>();
// 将数组里的字符串存储到 hashmap 中
for(String item : L){
if(wordCnt.containsKey(item)){
int value = wordCnt.get(item) + 1;
wordCnt.put(item, value);
}else
{
wordCnt.put(item, 1);
}
}
// 每次取出固定长度的字符串
for(int i = 0; i <= (int)S.length() - n * size; i++){
HashMap<String, Integer> strcnt = new HashMap<>();
int j = 0;
// 如该字串包含所有的数组内的字符串,那么它肯定连续遍历了 n 次
for(j = 0; j < n; j++){
String temp = S.substring(i + j * size,i + (j + 1) * size);
if(!wordCnt.containsKey(temp))
break;
// 单个字符串可能出现多次,所以这里为了便于比较,再开辟一个 hashmap,来比较次数
if(strcnt.containsKey(temp)){
int value = strcnt.get(temp) + 1;
strcnt.put(temp,value);
}else{
strcnt.put(temp,1);
}
if(strcnt.get(temp) > wordCnt.get(temp))
break;
}
if(j == n) list.add(i);
}
return list;
}