Skip to content

Commit 198c158

Browse files
committed
一刷140
1 parent 7d8768d commit 198c158

File tree

7 files changed

+113
-51
lines changed

7 files changed

+113
-51
lines changed

Diff for: README.adoc

+6-6
Original file line numberDiff line numberDiff line change
@@ -1006,12 +1006,12 @@ TIP: **公众号的微信号是: `jikerizhi`**。__因为众所周知的原因
10061006
|Medium
10071007
|
10081008

1009-
//|{counter:codes}
1010-
//|{leetcode_base_url}/word-break-ii/[140. Word Break II^]
1011-
//|{source_base_url}/_0140_WordBreakII.java[Java]
1012-
//|{doc_base_url}/0140-word-break-ii.adoc[题解]
1013-
//|Hard
1014-
//|
1009+
|{counter:codes}
1010+
|{leetcode_base_url}/word-break-ii/[140. Word Break II^]
1011+
|{source_base_url}/_0140_WordBreakII.java[Java]
1012+
|{doc_base_url}/0140-word-break-ii.adoc[题解]
1013+
|Hard
1014+
|
10151015

10161016
|{counter:codes}
10171017
|{leetcode_base_url}/linked-list-cycle/[141. Linked List Cycle^]

Diff for: docs/0000-26-dynamic-programming.adoc

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,15 @@ https://leetcode.cn/studyplan/dynamic-programming/[动态规划(基础版)^]
3131
. xref:0740-delete-and-earn.adoc[740. Delete and Earn]
3232
. xref:0062-unique-paths.adoc[62. Unique Paths]
3333
. xref:0063-unique-paths-ii.adoc[63. Unique Paths II]
34-
. xref:0980-unique-paths-iii.adoc[980. Unique Paths III] -- 这是一个回溯问题
34+
. xref:0980-unique-paths-iii.adoc[980. Unique Paths III] -- 这是一道回溯问题
3535
. xref:0064-minimum-path-sum.adoc[64. Minimum Path Sum]
3636
. xref:0120-triangle.adoc[120. Triangle]
3737
. xref:0931-minimum-falling-path-sum.adoc[931. Minimum Falling Path Sum]
3838
. xref:1289-minimum-falling-path-sum-ii.adoc[1289. Minimum Falling Path Sum II]
3939
. xref:0221-maximal-square.adoc[221. Maximal Square]
4040
. xref:0005-longest-palindromic-substring.adoc[5. Longest Palindromic Substring]
4141
. xref:0139-word-break.adoc[139. Word Break]
42-
. xref:0140-word-break-ii.adoc[140. Word Break II]
42+
. xref:0140-word-break-ii.adoc[140. Word Break II] -- 这是一道回溯题。
4343
. xref:0516-longest-palindromic-subsequence.adoc[516. Longest Palindromic Subsequence]
4444
. xref:1682-longest-palindromic-subsequence-ii.adoc[1682. Longest Palindromic Subsequence II]
4545
. xref:0072-edit-distance.adoc[72. Edit Distance]

Diff for: docs/0140-word-break-ii.adoc

+55-42
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,78 @@
11
[#0140-word-break-ii]
2-
= 140. Word Break II
2+
= 140. 单词拆分 II
33

4-
{leetcode}/problems/word-break-ii/[LeetCode - Word Break II^]
4+
https://leetcode.cn/problems/word-break-ii/[LeetCode - 140. 单词拆分 II ^]
55

6-
Given a *non-empty* string _s_ and a dictionary _wordDict_ containing a list of *non-empty* words, add spaces in _s_ to construct a sentence where each word is a valid dictionary word. Return all such possible sentences.
6+
给定一个字符串 `s` 和一个字符串字典 `wordDict`,在字符串 `s` 中增加空格来构建一个句子,使得句子中所有的单词都在词典中。*以任意顺序* 返回所有这些可能的句子。
77

8-
*Note:*
8+
**注意:**词典中的同一个单词可能在分段中被重复使用多次。
99

10+
*示例 1:*
1011

11-
* The same word in the dictionary may be reused multiple times in the segmentation.
12-
* You may assume the dictionary does not contain duplicate words.
12+
....
13+
输入:s = "catsanddog", wordDict = ["cat","cats","and","sand","dog"]
14+
输出:["cats and dog","cat sand dog"]
15+
....
1316

17+
*示例 2:*
1418

15-
*Example 1:*
19+
....
20+
输入:s = "pineapplepenapple", wordDict = ["apple","pen","applepen","pine","pineapple"]
21+
输出:["pine apple pen apple","pineapple pen apple","pine applepen apple"]
22+
解释: 注意你可以重复使用字典中的单词。
23+
....
1624

17-
[subs="verbatim,quotes,macros"]
18-
----
19-
*Input:
20-
*s = "`catsanddog`"
21-
wordDict = `["cat", "cats", "and", "sand", "dog"]`
22-
*Output:
23-
*`[
24-
"cats and dog",
25-
"cat sand dog"
26-
]`
25+
*示例 3:*
2726

28-
----
27+
....
28+
输入:s = "catsandog", wordDict = ["cats","dog","sand","and","cat"]
29+
输出:[]
30+
....
2931

30-
*Example 2:*
32+
*提示:*
3133

32-
[subs="verbatim,quotes,macros"]
33-
----
34-
*Input:
35-
*s = "pineapplepenapple"
36-
wordDict = ["apple", "pen", "applepen", "pine", "pineapple"]
37-
*Output:
38-
*[
39-
"pine apple pen apple",
40-
"pineapple pen apple",
41-
"pine applepen apple"
42-
]
43-
*Explanation:* Note that you are allowed to reuse a dictionary word.
34+
* `+1 <= s.length <= 20+`
35+
* `+1 <= wordDict.length <= 1000+`
36+
* `+1 <= wordDict[i].length <= 10+`
37+
* `s``wordDict[i]` 仅有小写英文字母组成
38+
* `wordDict` 中所有字符串都 *不同*
4439
45-
----
4640
47-
*Example 3:*
41+
== 思路分析
4842

49-
[subs="verbatim,quotes,macros"]
50-
----
51-
*Input:
52-
*s = "catsandog"
53-
wordDict = ["cats", "dog", "sand", "and", "cat"]
54-
*Output:
55-
*[]
56-
----
43+
看到所有可能就知道是回溯。
5744

45+
image::images/0140-01.png[{image_attr}]
5846

47+
使用 xref:0139-word-break.adoc[139. Word Break] 中的提到的回溯模式即可,感觉还不如 xref:0139-word-break.adoc[139. Word Break] 更有挑战。
5948

6049
[[src-0140]]
50+
[tabs]
51+
====
52+
一刷::
53+
+
54+
--
6155
[{java_src_attr}]
6256
----
63-
include::{sourcedir}/_0140_WordBreakII.java[tag=answer]
57+
include::{sourcedir}/_0140_WordBreakIi.java[tag=answer]
6458
----
59+
--
60+
61+
// 二刷::
62+
// +
63+
// --
64+
// [{java_src_attr}]
65+
// ----
66+
// include::{sourcedir}/_0140_WordBreakIi_2.java[tag=answer]
67+
// ----
68+
// --
69+
====
70+
71+
== 思考题
72+
73+
探索一下如何加上备忘录提高效率?
74+
75+
76+
== 参考资料
6577

78+
. https://leetcode.cn/problems/word-break-ii/solutions/468624/shou-hua-tu-jie-dan-ci-chai-fen-ii-cong-di-gui-dao/[140. 单词拆分 II - 「手画图解」单词拆分 II | 记忆化递归 | 思路剖析^]

Diff for: docs/images/0140-01.png

250 KB
Loading

Diff for: docs/index.adoc

+1-1
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ include::0138-copy-list-with-random-pointer.adoc[leveloffset=+1]
362362

363363
include::0139-word-break.adoc[leveloffset=+1]
364364

365-
// include::0140-word-break-ii.adoc[leveloffset=+1]
365+
include::0140-word-break-ii.adoc[leveloffset=+1]
366366

367367
include::0141-linked-list-cycle.adoc[leveloffset=+1]
368368

Diff for: logbook/202503.adoc

+5
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,11 @@ endif::[]
345345
|{doc_base_url}/0139-word-break.adoc[题解]
346346
|⭕️ 回溯+备忘录。首先想到的是回溯,但是超时(通过34/47的测试用例)。参考别人题解后,得到启发,加上备忘录通过。参考答案写出了动态规划的解法。*思考如何从基于回溯+备忘录转变为动态规划?*
347347

348+
|{counter:codes2503}
349+
|{leetcode_base_url}/word-break-ii/[140. 单词拆分 II^]
350+
|{doc_base_url}/0140-word-break-ii.adoc[题解]
351+
|✅ 回溯。没想到从 `LinkedList` 切换到 `ArrayList`,内存占用就大幅下降 43.77% → 91.82%。没有使用备忘录耗时已经击败了 98.49%。
352+
348353
|===
349354

350355
截止目前,本轮练习一共完成 {codes2503} 道题。
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package com.diguage.algo.leetcode;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
6+
public class _0140_WordBreakIi {
7+
// tag::answer[]
8+
/**
9+
* @author D瓜哥 · https://www.diguage.com
10+
* @since 2025-04-19 20:59:56
11+
*/
12+
public List<String> wordBreak(String s, List<String> wordDict) {
13+
List<String> result = new ArrayList<>(s.length());
14+
// 从 LinkedList 切换到 ArrayList,内存占用就大幅下降 43.77% → 91.82%
15+
List<String> path = new ArrayList<>(s.length());
16+
backtrack(s, wordDict, result, 0, path);
17+
return result;
18+
}
19+
20+
private void backtrack(String s, List<String> dict,
21+
List<String> result, int index, List<String> path) {
22+
if (s.length() < index) {
23+
return;
24+
}
25+
if (index == s.length()) {
26+
result.add(String.join(" ", path));
27+
return;
28+
}
29+
for (String word : dict) {
30+
int length = word.length();
31+
if (s.length() < index + length) {
32+
continue;
33+
}
34+
String substring = s.substring(index, index + length);
35+
// 使用 word.equals(substring),可以避免重复
36+
if (word.equals(substring)) {
37+
path.add(word);
38+
backtrack(s, dict, result, index + length, path);
39+
path.removeLast();
40+
}
41+
}
42+
}
43+
// end::answer[]
44+
}

0 commit comments

Comments
 (0)