题目1:139. Word Break
解法1:暴力backtracking
class Solution:
def wordBreak(self, s: str, wordDict: List[str]) -> bool:
def backtracking(start):
nonlocal ans
if start == len(s):
ans = True
for i in range(start+1,len(s)+1):
if s[start:i] in dic:
backtracking(i)
dic = {}
for word in wordDict:
dic[word] = True
ans = False
backtracking(0)
return ans
解法2:backtrack+memorization
class Solution:
def wordBreak(self, s: str, wordDict: List[str]) -> bool:
def backtracking(start):
#nonlocal ans
if start in memo:
return memo[start]
if start == len(s):
return True
flag = False
for i in range(start+1,len(s)+1):
if s[start:i] in dic:
flag = flag or backtracking(i)
memo[start] = flag
return memo[start]
dic = {}
for word in wordDict:
dic[word] = True
ans = False
memo = {}
backtracking(0)
return memo[0]
解法3:动态规划
等同于backtrack+memorization
class Solution:
def wordBreak(self, s: str, wordDict: List[str]) -> bool:
dp = [0]*(len(s)+1)
dp[0] = True
for i in range(1,len(s)+1):
for j in range(i):
if s[j:i] in wordDict and dp[j]:
dp[i] = True
return dp[-1]
题目2:140. Word Break II变种
假设这道题目只要求方案的个数,那么依旧可以用backtrack+memorization来做
class Solution:
def wordBreak(self, s: str, wordDict: List[str]) -> List[str]:
dp = [0]*(len(s)+1)
dp[0] = 1
for i in range(1,len(s)+1):
for j in range(i):
if s[j:i] in wordDict:
dp[i] += dp[j]
print(dp[-1])
但是如果是要输出所有的方案,dp肯定就行不通了,下面必须要用backtracking才可以输出所有的方案数,因为dp只能保存一个状态值,而不能保存这个状态本身
解法1:backtracking
class Solution:
def wordBreak(self, s: str, wordDict: List[str]) -> List[str]:
def backtracking(start,comb):
if start == len(s):
ans.append(comb[:])
for i in range(start+1,len(s)+1):
if s[start:i] in wordDict:
comb.append(s[start:i])
backtracking(i,comb)
comb.pop()
ans = []
backtracking(0,[])
res = []
for l in ans:
res.append(' '.join(l))
return res
解法2:backtrack+memorization
class Solution:
def wordBreak(self, s: str, wordDict: List[str]) -> List[str]:
def backtracking(start):
if start in memo:
return memo[start]
if start == len(s):
return ['']
results = []
for i in range(start+1,len(s)+1):
if s[start:i] in wordDict:
for sub in backtracking(i):
if sub:
results.append(s[start:i] + ' ' +sub)
else:
results.append(s[start:i])
memo[start] = results
return memo[start]
memo = {}
return(backtracking(0))
这边的memorization需要一些技巧,时间复杂度应该是与输出的答案同级别的
题目3:131. Palindrome Partitioning
这道题目看起来不一样,实际上是与word break题目是一模一样的。只是workbreak题目切分判断条件是当前的子串是否在wordDict中,而这边则是判断子串是不是回文,可以看到下面的代码除了判断条件,其他的与上面的解法一模一样
class Solution:
def partition(self, s: str) -> List[List[str]]:
def backtracking(start,comb):
if start == len(s):
ans.append(comb[:])
for i in range(start+1,len(s)+1):
if s[start:i] == s[start:i][::-1]:
comb.append(s[start:i])
backtracking(i,comb)
comb.pop()
ans = []
backtracking(0,[])
return ans