Skip to content

Commit 09d0d2c

Browse files
committed
Add Solutin and README.md for 030 [Java]
1 parent f901b65 commit 09d0d2c

File tree

2 files changed

+149
-0
lines changed

2 files changed

+149
-0
lines changed
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
## 与所有单词相关联的字串
2+
### 题目描述
3+
给定一个字符串 s 和一些长度相同的单词 words。在 s 中找出可以恰好串联 words 中所有单词的子串的起始位置。
4+
5+
注意子串要与 words 中的单词完全匹配,中间不能有其他字符,但不需要考虑 words 中单词串联的顺序。
6+
7+
```
8+
示例 1:
9+
10+
输入:
11+
s = "barfoothefoobarman",
12+
words = ["foo","bar"]
13+
输出: [0,9]
14+
解释: 从索引 0 和 9 开始的子串分别是 "barfoor" 和 "foobar" 。
15+
输出的顺序不重要, [9,0] 也是有效答案。
16+
示例 2:
17+
18+
输入:
19+
s = "wordgoodstudentgoodword",
20+
words = ["word","good","good"]
21+
(ps:原题的例子为 words = ["word","student"] 和题目描述不符,这里私自改了一下)
22+
输出: []
23+
```
24+
25+
### 解法
26+
1. 用 HashMap< 单词, 出现次数 > map 来存储所有单词;
27+
2. 设单词数量为 N ,每个单词长度为 len,则我们只需要对比到 **str.length() - N \* len** ,
28+
再往后因为不足 N \* len 个字母,肯定不匹配;
29+
3. 每次从 str 中选取连续的 N \* len 个字母进行匹配时,**从后向前匹配**,因为若后面的单词不匹配,
30+
无论前面的单词是否匹配,当前选取的字串一定不匹配,且,最后一个匹配的单词前的部分一定不在匹配的字串中,
31+
这样下一次选取长度为 N \* len 的字串时,可以**从上次匹配比较中最后一个匹配的单词开始**,减少了比较的次数;
32+
4. 考虑到要点 3 中对前一次匹配结果的利用,遍历 str 时,采用间隔为 len 的形式。
33+
例如示例 1 ,遍历顺序为:(0 3 6 9 12 15) (1 4 7 10 13)(2 5 8 11 14)
34+
35+
36+
```java
37+
class Solution {
38+
public List<Integer> findSubstring(String s, String[] words) {
39+
40+
List<Integer> re = new ArrayList<>();
41+
42+
if(s == null || words == null || words.length == 0 || words[0] == null) {
43+
return re;
44+
}
45+
if(s.length() == 0 || words[0].length() == 0 || s.length() < words.length * words[0].length()) {
46+
return re;
47+
}
48+
// 用< 单词,出现次数 > 来存储 words 中的元素,方便查找
49+
HashMap<String,Integer> map = new HashMap();
50+
for (String string : words) {
51+
map.put(string, map.getOrDefault(string,0) + 1);
52+
}
53+
int len = words[0].length();
54+
int strLen = s.length();
55+
int lastStart = len * words.length - len;
56+
57+
for (int i = 0; i < len; i++) {
58+
for (int j = i; j <= strLen - len - lastStart; j += len) {
59+
String tempStr = s.substring(j, j + len);
60+
if(map.containsKey(tempStr)) {
61+
HashMap<String,Integer> searched = new HashMap<>();
62+
// 从后向前依次对比
63+
int tempIndex = j + lastStart;
64+
String matchedStr = s.substring(tempIndex, tempIndex + len);
65+
while (tempIndex >= j && map.containsKey(matchedStr)) {
66+
// 正确匹配到单词
67+
if(searched.getOrDefault(matchedStr,0) < map.get(matchedStr)) {
68+
searched.put(matchedStr, searched.getOrDefault(matchedStr,0) + 1);
69+
}
70+
else {
71+
break;
72+
}
73+
tempIndex -= len;
74+
if(tempIndex < j) {
75+
break;
76+
}
77+
matchedStr = s.substring(tempIndex, tempIndex + len);
78+
}
79+
// 完全匹配所以单词
80+
if(j > tempIndex) {
81+
re.add(j);
82+
}
83+
// 从tempIndex 到 tempIndex + len 这个单词不能正确匹配
84+
else {
85+
j = tempIndex;
86+
}
87+
}
88+
}
89+
}
90+
return re;
91+
}
92+
}
93+
```
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
class Solution {
2+
public List<Integer> findSubstring(String s, String[] words) {
3+
4+
List<Integer> re = new ArrayList<>();
5+
6+
if(s == null || words == null || words.length == 0 || words[0] == null) {
7+
return re;
8+
}
9+
if(s.length() == 0 || words[0].length() == 0 || s.length() < words.length * words[0].length()) {
10+
return re;
11+
}
12+
// 用< 单词,出现次数 > 来存储 words 中的元素,方便查找
13+
HashMap<String,Integer> map = new HashMap();
14+
for (String string : words) {
15+
map.put(string, map.getOrDefault(string,0) + 1);
16+
}
17+
int len = words[0].length();
18+
int strLen = s.length();
19+
int lastStart = len * words.length - len;
20+
21+
for (int i = 0; i < len; i++) {
22+
for (int j = i; j <= strLen - len - lastStart; j += len) {
23+
String tempStr = s.substring(j, j + len);
24+
if(map.containsKey(tempStr)) {
25+
HashMap<String,Integer> searched = new HashMap<>();
26+
// 从后向前依次对比
27+
int tempIndex = j + lastStart;
28+
String matchedStr = s.substring(tempIndex, tempIndex + len);
29+
while (tempIndex >= j && map.containsKey(matchedStr)) {
30+
// 正确匹配到单词
31+
if(searched.getOrDefault(matchedStr,0) < map.get(matchedStr)) {
32+
searched.put(matchedStr, searched.getOrDefault(matchedStr,0) + 1);
33+
}
34+
else {
35+
break;
36+
}
37+
tempIndex -= len;
38+
if(tempIndex < j) {
39+
break;
40+
}
41+
matchedStr = s.substring(tempIndex, tempIndex + len);
42+
}
43+
// 完全匹配所以单词
44+
if(j > tempIndex) {
45+
re.add(j);
46+
}
47+
// 从tempIndex 到 tempIndex + len 这个单词不能正确匹配
48+
else {
49+
j = tempIndex;
50+
}
51+
}
52+
}
53+
}
54+
return re;
55+
}
56+
}

0 commit comments

Comments
 (0)