LeetCode30 串联所有单词的子串
hashmap何时使用
在涉及字符串S是否在字符串P中被包含,或者寻找特定字符,只要是找值,或者是要求是否符合某个特征,都可以用hashmap。
那么本题利用hashmap更是一种巧妙地方法。算法如下:
创建两个hashmap,一个存储单词,一个存储模式串中子串中单词出现个数。
将所有单词放到hashmap1中,并记录所有单词出现的次数。
接下来对子串进行扫描:
如果字串不出现在hashmap1中,则跳过进行下一轮循环,
如果在hashmap1中,放到hashmap2中,如果hashmap2与hashmap1中存放的内容一致时,即可满足答案。
本题注意单词长度相同。
解法一:
public List
<Integer> findSubstring(String s
, String
[] words
) {
List
<Integer> res
= new ArrayList<Integer>();
int wordNum
= words
.length
;
if (wordNum
== 0) {
return res
;
}
int wordLen
= words
[0].length();
HashMap
<String, Integer> allWords
= new HashMap<String, Integer>();
for (String w
: words
) {
int value
= allWords
.getOrDefault(w
, 0);
allWords
.put(w
, value
+ 1);
}
for (int i
= 0; i
< s
.length() - wordNum
* wordLen
+ 1; i
++) {
HashMap
<String, Integer> hasWords
= new HashMap<String, Integer>();
int num
= 0;
while (num
< wordNum
) {
String word
= s
.substring(i
+ num
* wordLen
, i
+ (num
+ 1) * wordLen
);
if (allWords
.containsKey(word
)) {
int value
= hasWords
.getOrDefault(word
, 0);
hasWords
.put(word
, value
+ 1);
if (hasWords
.get(word
) > allWords
.get(word
)) {
break;
}
} else {
break;
}
num
++;
}
if (num
== wordNum
) {
res
.add(i
);
}
}
return res
;
}
解法二:
解法二是对解法一的优化,因为解法一每次只是移动一个字符,浪费效率,
所以解法二每次移动单词长度个字符。
但是要分情况进行讨论:
请参考以下文章:
https://leetcode-cn.com/problems/substring-with-concatenation-of-all-words/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by-w-6/
public List
<Integer> findSubstring(String s
, String
[] words
) {
List
<Integer> res
= new ArrayList<Integer>();
int wordNum
= words
.length
;
if (wordNum
== 0) {
return res
;
}
int wordLen
= words
[0].length();
HashMap
<String, Integer> allWords
= new HashMap<String, Integer>();
for (String w
: words
) {
int value
= allWords
.getOrDefault(w
, 0);
allWords
.put(w
, value
+ 1);
}
for (int j
= 0; j
< wordLen
; j
++) {
HashMap
<String, Integer> hasWords
= new HashMap<String, Integer>();
int num
= 0;
for (int i
= j
; i
< s
.length() - wordNum
* wordLen
+ 1; i
= i
+ wordLen
) {
boolean hasRemoved
= false;
while (num
< wordNum
) {
String word
= s
.substring(i
+ num
* wordLen
, i
+ (num
+ 1) * wordLen
);
if (allWords
.containsKey(word
)) {
int value
= hasWords
.getOrDefault(word
, 0);
hasWords
.put(word
, value
+ 1);
if (hasWords
.get(word
) > allWords
.get(word
)) {
hasRemoved
= true;
int removeNum
= 0;
while (hasWords
.get(word
) > allWords
.get(word
)) {
String firstWord
= s
.substring(i
+ removeNum
* wordLen
, i
+ (removeNum
+ 1) * wordLen
);
int v
= hasWords
.get(firstWord
);
hasWords
.put(firstWord
, v
- 1);
removeNum
++;
}
num
= num
- removeNum
+ 1;
i
= i
+ (removeNum
- 1) * wordLen
;
break;
}
} else {
hasWords
.clear();
i
= i
+ num
* wordLen
;
num
= 0;
break;
}
num
++;
}
if (num
== wordNum
) {
res
.add(i
);
}
if (num
> 0 && !hasRemoved
) {
String firstWord
= s
.substring(i
, i
+ wordLen
);
int v
= hasWords
.get(firstWord
);
hasWords
.put(firstWord
, v
- 1);
num
= num
- 1;
}
}
}
return res
;
}