Leetcode wordbreak类型的序列问题

题目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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值