题目
给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。
说明:
拆分时可以重复使用字典中的单词。
你可以假设字典中没有重复的单词。
示例 1:
输入: s = "leetcode", wordDict = ["leet", "code"]
输出: true
解释: 返回 true 因为 "leetcode" 可以被拆分成 "leet code"。
示例 2:
输入: s = "applepenapple", wordDict = ["apple", "pen"]
输出: true
解释: 返回 true 因为 "applepenapple" 可以被拆分成 "apple pen apple"。
注意你可以重复使用字典中的单词。
示例 3:
输入: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"]
输出: false
解题思路
DP
Use dp[i][j]
to denote whether the s[i:j+1]
could be found in wordDict, the transform equation would be:
d
p
[
i
]
[
j
]
=
s
[
i
:
j
+
1
]
in wordDict
∪
(
d
p
[
i
]
[
k
]
∩
d
p
[
k
+
1
]
[
j
]
)
,
∀
i
<
=
k
<
j
dp[i][j] = s[i:j+1] \text{ in wordDict} \; \cup \; (dp[i][k] \cap dp[k+1][j]) , \forall i <= k < j
dp[i][j]=s[i:j+1] in wordDict∪(dp[i][k]∩dp[k+1][j]),∀i<=k<j
We would only use the upper triangle of the matrix, and since we have to iterate all the columns at each position, the time complexity would be
c
o
l
2
∗
r
o
w
{col}^2 * row
col2∗row
Time complexity:
o
(
n
3
)
o(n^3)
o(n3) where n = len(s)
Space complexity:
o
(
n
2
)
o(n^2)
o(n2)
Reduced DP
Since we only use upper triangle of the matrix, it’s actually could be reduced from a matrix to list. Use dp[i]
to denote that whether s[:i]
could be segmented and included in wordDict
, then the transform equation would be:
d
p
[
i
]
=
d
p
[
k
]
∩
(
s
[
k
:
i
]
in wordDict
)
,
∀
0
≤
k
<
i
dp[i] = dp[k] \cap (s[k:i] \text{ in wordDict}), \forall \;0\leq k < i
dp[i]=dp[k]∩(s[k:i] in wordDict),∀0≤k<i
Note that dp[i]
doesn’t include s[i]
, we may need to add an initial value for s[0]
.
Time complexity:
o
(
n
2
)
o(n^2)
o(n2)
Space complexity:
o
(
n
)
o(n)
o(n)
代码
DP
class Solution:
def wordBreak(self, s: str, wordDict: List[str]) -> bool:
n = len(s)
dp = [[False] * n for _ in range(n)]
# initialize
for i in range(n):
if s[i] in wordDict:
dp[i][i] = True
for i in range(n - 2, -1, -1):
for j in range(i + 1, n):
for k in range(i, j):
dp[i][j] |= dp[i][k] & dp[k + 1][j]
dp[i][j] |= s[i:j + 1] in wordDict
return dp[0][n - 1]
Reduced DP
class Solution:
def wordBreak(self, s: str, wordDict: List[str]) -> bool:
dp = [True] + [False] * len(s)
for i in range(1, len(s) + 1):
for k in range(i):
dp[i] |= dp[k] & (s[k:i] in wordDict)
return dp[len(s)]