边工作边刷题:70天一遍leetcode: day 89

时间:2024-01-07 19:04:32

Word Break I/II

现在看都是小case题了,一遍过了。注意这题不是np complete,dp解的time complexity可以是O(n^2) or O(nm) (取决于inner loop是i还是m)。所有解的个数是exponential的 (比如”aaaa....”, dict="a, aa”,每层都有2个选择)。以前在amazon onsite遇到过,不过既不是返回True/False,也不是所有解,而是一个解。其实一个解和True/False是一个复杂度,因为单一解是可以从dp反向重构的。而recursion的唯一解为什么也是O(n^2)? 每层最多循环n次,而要得到的就是长度为n-start = n,n-1,…, 1的情况:而每层向下同样得到n-start的情况,所以最多n层。结果是n^2

II为什么只存possible,而不存所有中间结果?结果可能是指数级的,会超过memory limit

class Solution(object):
    def wordBreak(self, s, wordDict):
        """
        :type s: str
        :type wordDict: Set[str]
        :rtype: bool
        """
        n = len(s)
        dp = [False]*(n+1)
        dp[0]=True
        for i in range(1, n+1):
            for j in range(i):
                if s[j:i] in wordDict and dp[j]:
                    dp[i]=True

        return dp[n]
class Solution(object):
    def wordBreak(self, s, wordDict):
        """
        :type s: str
        :type wordDict: Set[str]
        :rtype: List[str]
        """
        def wordRec(s, start, wordDict, possible, res, solution):
            n = len(s)
            if start==n:
                resCp = list(res)
                solution.append(' '.join(resCp))
                return

            for i in range(start+1, n+1):
                if s[start:i] in wordDict and (i==n or possible[i]):
                    ns = len(solution)
                    res.append(s[start:i])
                    wordRec(s, i, wordDict, possible, res, solution)
                    res.pop()
                    if len(solution)==ns:
                        possible[i]=False

        res =[]
        solution = []
        possible = [True]*len(s)
        wordRec(s, 0, wordDict, possible, res, solution)
        return solution