30 Day Challenge Day 21 | Leetcode 139. Word Break

题解

Medium

动态规划

class Solution {
public:
    bool wordBreak(string s, vector<string>& wordDict) {
        // a + b = s
        // as long as a true and b true, then s true
        // dp[i]: i represents the sub string from 0 to i
        // find dp[n-1]
        vector<bool> dp(s.size()+1, false);
        dp[0] = true; // assume an empty word is always existing in dict
        
        for(int i = 1; i <= s.size(); i++) {
            for(int j = 0; j < i; j++) {
                if(dp[j] && find(wordDict.begin(), wordDict.end(), s.substr(j, i-j)) != wordDict.end()) {
                    dp[i] = true;
                    break;
                }
            }
        }
        
        return dp[s.size()];
    }
};

递归加记忆

这是很经典很有代表性的一题,可以用多种方法做出来。当然,最佳方法是用动态规划。

应该几种方法多试一下,在面试环境下,不一定能够第一时间找到最佳方法,最好有第二解法做候补。

其实这种题,能用动态规划来做,往往就能用回溯加记忆矩阵的方法来做,记忆矩阵这里充当了动态规划矩阵的作用,思想是一样的,“不必重复去解决已解决的问题”。只不过动态规划在代码上显得更舒服一些。

class Solution {
public:
    bool wordBreak(string s, vector<string>& wordDict) {
        unordered_set wordSet(wordDict.begin(), wordDict.end());
        vector<int> memo(s.size(), -1);
        return helper(s, wordSet, 0, memo);
    }
    
    bool helper(string s, unordered_set<string>& wordSet, int start, vector<int>& memo) {
        // memo[i]: the substring form i to size-1
        if(start == s.size()) return true; // empty word
        
        // first check if this has been solved before
        if(memo[start] != -1) return memo[start];
        
        // divide problem into start to i, and i to end
        for(int i = start; i <= s.size(); i++) {
            if(wordSet.count(s.substr(start, i-start)) && helper(s, wordSet, i, memo)) {
                memo[start] = 1;
                return true;
            }    
        }
        
        memo[start] = 0;
        return false;
    }
};
原文地址:https://www.cnblogs.com/casperwin/p/13783492.html