用python写leetcode【2】 --单词拆分(139)、单词拆分2(140)

这篇博客主要介绍了如何使用Python解决LeetCode的两个单词拆分问题:139题和140题。通过对给定字符串s和字典wordDict进行动态规划分析,确定字符串能否被拆分为字典中的单词。139题重点在于判断拆分可行性,而140题则需要找出所有可能的拆分句子。博主分享了两种不同方法的思路和代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

单词拆分(139)

题目

给定一个非空字符串 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判断,dp[i]表示前i个字符组成的字符串能否成功拆分。从i= 0开始之后每次添加了一个字符,循环判断能否与之前的组合成新的划分。时间复杂度为n*n

代码

      class Solution:
        def wordBreak(self, s, wordDict):
            """
            :type s: str
            :type wordDict: List[str]
            :rtype: bool
            """
            dp = [True]
            lenght = len(s)
            i = 1
            while i < lenght + 1:
                dp.append(False)
                j = i-1
                while j >= 0:
                    if dp[j] and s[j:i] in wordDict:
                        dp[i] = True
                        break
                    j -= 1
                i += 1
            return dp[len(s)]

单词拆分2(140)

题目

给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,在字符串中增加空格来构建一个句子,使得句子中所有的单词都在词典中。返回所有这些可能的句子。

说明:

分隔时可以重复使用字典中的单词。
你可以假设字典中没有重复的单词。
示例 1:

输入:
s = “catsanddog”
wordDict = [“cat”, “cats”, “and”, “sand”, “dog”]
输出:
[
“cats and dog”,
“cat sand dog”
]
示例 2:

输入:
s = “pineapplepenapple”
wordDict = [“apple”, “pen”, “applepen”, “pine”, “pineapple”]
输出:
[
“pine apple pen apple”,
“pineapple pen apple”,
“pine applepen apple”
]
解释: 注意你可以重复使用字典中的单词。

思路

一开始的思路是根据上一题的方法,任然采用动态规划的方法,只不过在每一次动态规划过程中不仅记录是否可以拆分,还要把所有的拆分形式记录下来,但在最后提交时,卡在了第31个测试集上,原因是内存消耗过多。无奈只能用其他的方法。再阅读了有关资料后,使用dp(动态规划)判断能否分割,如果可以分割采用DFS分割。DFS分割的思路即每次从字典中找可以与字符串开头匹配的,并将后续的传入做下一次迭代。
简单分析了一下性能后,的确后者方法无论在空间或者时间上都有巨大优势,动态规划适用于拆分的特例(如能否拆分的判断),对于遍历的问题还需要用搜索到方法。

代码

    class Solution:
    """
    采用139的动态规划的思路,内存消耗过大,失败
    """
        def wordBreak(self, s: str, wordDict) :
            m = len(s)
            yes = [False]*(m+1)
            yes[0] = True
            ans = {}
            for i in range(m+1):
                ans[i]=[]
            
            for i in range(1,m+1):
                if i-smax-3>0:                 
                for j in range(i-1,-1,-1) :
                    if yes[j] is True and s[j:i] in wordDict:
                        yes[i]=True
                        if len(ans[j])==0 :
                            ans[i].append(s[j:i])
                        else:
                            for k in ans[j]:
                                temp = k+' '+s[j:i]
                                ans[i].append(temp)
            
            return ans[m]

     class Solution(object):
        def wordBreak(self, s, wordDict):
            """
            :type s: str
            :type wordDict: List[str]
            :rtype: List[str]
            """
            tmp=wordDict[:]
            wordDict={}
            for w in tmp:
                wordDict[w]=1
            res=[]
            tmp=[]
            def check(s): # 判断是不是可以拆分
                l=len(s)
                dp=[False]*(l+1)
                dp[0]=True
                for i in range(l):
                    for j in range(i,-1,-1):
                        if dp[j] and s[j:i+1] in wordDict:
                            dp[i+1]=True
                            break
                return dp[l]
            def dfs(s):
                if not s:#s为空拆分到头
                    res.append(tmp[:])
                    return
                for word in wordDict:
                    l=len(word)
                    if word==s[:l]:
                        tmp.append(word)                
                        dfs(s[l:])
                        tmp.pop()
            if check(s):
                dfs(s)
            r=[]
            for e in res:
                r.append(" ".join(e))#转化形式
            return r
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值