zoukankan      html  css  js  c++  java
  • 【Leetcode刷题】单词拆分

    139. 单词拆分

    https://leetcode-cn.com/problems/word-break/

    class Solution(object):
        def wordBreak(self, s, wordDict):
            """
            :type s: str
            :type wordDict: List[str]
            :rtype: bool
            """
            # dp[i]表示s[:i]能否被拆分
            # 如何计算dp[i]:枚举以s[i-1]结尾的字符串片段s[j:i]
            # dp[i] = dp[j] && s[j:i] in wordDict
            # 初始化dp[0]=True。最终返回dp[n]
            if not wordDict:
                return False
            n = len(s)
            dp = [False for _ in range(n+1)]
            dp[0] = True
            # set的搜索只需要O(1)的时间复杂度,而list需要O(n)
            word_set = set(wordDict)
            # 单词的最大长度
            max_len = max(len(word) for word in word_set)
            for i in range(1, n+1):
                # s[j:i]的长度应小于或等于单词的最大长度
                board = max(0, i - max_len)
                j = i - 1
                while j >= board:
                    if dp[j] and (s[j:i] in word_set):
                        dp[i] = True
                        break
                    j -= 1
            return dp[n]
    

    时间复杂度:O(n^2)。需要枚举n个状态,每个状态需要枚举n个分割点 j,set的搜索需要O(1)的时间复杂度,因此总的时间复杂度为O(n^2)

    空间复杂度:O(n)

    140. 单词拆分 II

    https://leetcode-cn.com/problems/word-break-ii/

    class Solution(object):
        def wordBreak(self, s, wordDict):
            """
            :type s: str
            :type wordDict: List[str]
            :rtype: List[str]
            """
            if not wordDict:
                return []
            # dp[i]记录所有以s[i-1]结尾的单词起始位置
            # 如何计算dp[i]:枚举以s[i-1]结尾的字符串片段s[j:i]
            # if dp[j] && s[j:i] in wordDict, dp[i].append(j)
            # 然后从后往前深度优先遍历
            n = len(s)
            dp = [[] for _ in range(n + 1)]
            # dp[0]=True。考虑匹配到第一个单词s[0:i]时,dp[i+1]=[0]
            dp[0] = True
            # 单词的最大长度,往前找到这个长度还找不到就不需要再找下去了
            max_len = max(len(word) for word in wordDict)
            # set的搜索只需要O(1)的时间复杂度,而list需要O(n)
            word_set = set(wordDict)
            for i in range(1, n + 1):
                # 注意下界的取值,下界是取不到的,所以要-1
                for j in range(i - 1, max(0, i - max_len) - 1, -1):
                    # 找到所有以s[i-1]结尾的单词起始位置
                    if s[j:i] in word_set and dp[j]:
                        dp[i].append(j)
    
            words_list = []
            # 当前路径
            words = []
    
            def dfs(i):
                # 一条能够全部拆分的路径最终会取到dp[0]
                if i == 0:
                    words_list.append(words[:])
                    return
                for j in dp[i]:
                    # 将单词取出
                    words.append(s[j:i])
                    dfs(j)
                    # 回溯
                    words.pop()
    
            dfs(n)
            result = []
            for words in words_list:
                result.append(" ".join(word for word in words[::-1]))
            return result
    

    本题的时间与空间复杂度均为指数级别,较难进行具体的分析

  • 相关阅读:
    STM32寄存器的简介、地址查找,与直接操作寄存器
    SPI初始化寄存器配置
    docker 命令
    SpringBoot接口格式和规范
    算法
    RabbitMQ
    UML概念
    activeMQ和JMS
    设计模式七大原则
    redis缓存
  • 原文地址:https://www.cnblogs.com/luozx207/p/13914573.html
Copyright © 2011-2022 走看看