LeetCode 139 单词拆分

LeetCode 139 单词拆分

🟠 中等偏上

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

不好的思路:类似于换零钱问题,index遍历零钱。如果从字典中拿一个字符,能在主串中匹配,那么有选或不选两种可能,不匹配就不选。但是这样就要每次都要匹配一下,并且切割剩下的串不能合并,增加复杂程度。

好的思路:index遍历主串,把index前面的切下来,去字典中比较,匹配到就有两种选择,不匹配就直接不选。好像分割回文串的问题[分割回文串](../04 回溯/LeetCode 131 分割回文串 - 回溯解法.md)

根据 [分割回文串](../04 回溯/LeetCode 131 分割回文串 - 回溯解法.md) 写出本题递归代码

class Solution {

public:

    bool del_word(string& s, int pre, unordered_set<string>& word_set) {
		//如果左边分完了,返回true
        if (pre == s.size()) {

            return true;

        }

        for (int i = 1; pre + i <= s.size(); i++) {
			//如果左边是集合中的一个,那么分割右边
            if (word_set.count(s.substr(pre, i))) {

                if (del_word(s, pre + i, word_set)) {

                    return true;

                }

            }

        }

        return false;

    }

    bool wordBreak(string s, vector<string>& wordDict) {

        auto word_set = unordered_set<string>();

        for (auto word : wordDict) {

            word_set.insert(word);

        }

        return del_word(s,0,word_set);

    }

};

改为动态规划

分析:递归输入是pre一位变量,因此dp为一维数组,因为pre从0到size,因此大小为size+1, 本层递归返回值依赖于很多 del_word(s,pre + i,word_set) 的返回值。这些的传入变量都比pre大,因此从大的向小的遍历。

class Solution {

public:

    bool del_word(string& s, int pre, unordered_set<string>& word_set) {

        if (pre == s.size()) {

            return true;

        }

        for (int i = 1; pre + i <= s.size(); i++) {

            if (word_set.count(s.substr(pre, i))) {

                if (del_word(s, pre + i, word_set)) {

                    return true;

                }

            }

        }

        return false;

    }

    bool wordBreak(string s, vector<string>& wordDict) {

        auto word_set = unordered_set<string>();

        for (auto word : wordDict) {

            word_set.insert(word);

        }

        vector<bool> dp(s.size() + 1, false);

        dp[s.size()] = true;

        for (int i = s.size() - 1; i >= 0; i--) {

            for (int len = 1; i + len <= s.size(); len++) {

                if (word_set.count(s.substr(i, len)) && dp[i + len]) {

                    dp[i] = true;

                    break;

                }

            }

        }

        // return del_word(s,0,word_set);

        return dp[0];

    }

};