Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 8d9426f

Browse files
author
robot
committed
feat: 139ドル
1 parent 383f7ac commit 8d9426f

File tree

1 file changed

+49
-9
lines changed

1 file changed

+49
-9
lines changed

‎problems/139.word-break.md

Lines changed: 49 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,17 +44,38 @@ https://leetcode-cn.com/problems/word-break/
4444

4545
这道题是给定一个字典和一个句子,判断该句子是否可以由字典里面的单词组出来,一个单词可以用多次。
4646

47-
暴力的方法是无解的,复杂度极其高。 我们考虑其是否可以拆分为小问题来解决。
48-
对于问题`(s, wordDict)` 我们是否可以用(s', wordDict) 来解决。 其中 s' 是 s 的子序列,
49-
当 s'变成寻常(长度为 0)的时候问题就解决了。 我们状态转移方程变成了这道题的难点。
47+
暴力的方法是无解的,复杂度比较高,但是可以通过。
5048

51-
我们可以建立一个数组 dp, dp[i]代表 字符串 s.substring(0, i) 能否由字典里面的单词组成,经过这样的抽象我们就可以建立 dp[i - word.length] 和 dp[i] 的关系。它们有什么关系?又该如何转移呢?
49+
暴力思路是从匹配位置 0 开始匹配, 在 wordDict 中一个个找,如果其能和 s 匹配上就尝试进行匹配,并更新匹配位置。
50+
51+
比如 s = "leetcode", wordDict = ["leet", "code"]
52+
53+
那么:
54+
55+
- 先试试 leet 可以匹配么?可以的,匹配后 s 剩下 code,继续在 wordDict 中找。
56+
- leet 可以匹配么?不能!code 能够匹配么?可以!返回 true 结束
57+
58+
如果 wordDict 遍历一次没有任何进展,那么直接返回 false。
59+
60+
注意到如果匹配成功一次后,本质是把问题规模缩小了,问题性质不变,因此可以使用动态规划来解决。
61+
62+
```py
63+
@cache
64+
def dp(pos):
65+
if pos == len(s): return True
66+
for word in wordDict:
67+
if s[pos:pos+len(word)] == word and dp(pos + len(word)): return True
68+
return False
69+
return dp(0)
70+
```
71+
72+
复杂度为 $O(n^2 * m)$ 其中 n 为 s 长度, m 为 wordDict 长度。
5273

5374
我们用图来感受一下:
5475

5576
![139.word-break-1](https://p.ipic.vip/5b21ws.jpg)
5677

57-
没有明白也没有关系,我们分步骤解读一下:
78+
接下来我们以题目给的例子分步骤解读一下:
5879

5980
(以下的图左边都代表 s,右边都是 dict,灰色代表没有处理的字符,绿色代表匹配成功,红色代表匹配失败)
6081

@@ -71,9 +92,28 @@ https://leetcode-cn.com/problems/word-break/
7192

7293
![139.word-break-6](https://p.ipic.vip/yu4j2f.jpg)
7394

95+
我们可以进一步优化, 使得复杂度和 m 无关。优化的关键是在 dp 函数内部枚举匹配的长度 k。这样我们截取 s[pos:pos+k] 其中 pos 表示当前匹配到的位置。然后只要看 s[pos:pos+k] 在 wordDict 存在与否就行。存在了就更新匹配位置继续,不存在就继续。而*看 s[pos:pos+k] 在 wordDict 存在与否就行* 是可以通过将 wordDict 中放入哈希集合中进行优化的,时间复杂度 O(1),牺牲一点空间,空间复杂度 O(m)
96+
7497
## 代码
7598

76-
代码支持: JS,CPP
99+
代码支持: Python3, JS,CPP
100+
101+
Python3 Code:
102+
103+
```py
104+
class Solution:
105+
def wordBreak(self, s: str, wordDict: List[str]) -> bool:
106+
wordDict = set(wordDict)
107+
@cache
108+
def dp(pos):
109+
if pos == len(s): return True
110+
cur = ''
111+
for nxt in range(pos, len(s)):
112+
cur += s[nxt]
113+
if cur in wordDict and dp(nxt + 1): return True
114+
return False
115+
return dp(0)
116+
```
77117

78118
JS Code:
79119

@@ -123,10 +163,10 @@ public:
123163
124164
**复杂度分析**
125165
126-
SW 分别为字符串和字典的长度。
166+
nm 分别为字符串和字典的长度。
127167
128-
- 时间复杂度:$O(S ^ 3)$
129-
- 空间复杂度:$O(S + W)$
168+
- 时间复杂度:$O(n ^ 2)$
169+
- 空间复杂度:$O(m)$
130170
131171
大家对此有何看法,欢迎给我留言,我有时间都会一一查看回答。更多算法套路可以访问我的 LeetCode 题解仓库:https://github.com/azl397985856/leetcode 。 目前已经 37K star 啦。
132172
大家也可以关注我的公众号《力扣加加》带你啃下算法这块硬骨头。

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /