Leetcode:139. 单词拆分(C++)

目录

问题描述:

实现代码与解析:

动态规划(完全背包):

原理思路:


问题描述:

        给你一个字符串 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

实现代码与解析:

动态规划(完全背包):

class Solution {
public:
    bool wordBreak(string s, vector& wordDict)
    {
        //完全背包,需要考虑顺序
        vector dp(s.size() + 1, false);// dp数组
        dp[0] = true;// 初始化        
        // 遍历背包
        for (int j = 0; j <= s.size(); j++)
        {
            // 遍历物品
            for (int i = 0; i < j; i++)
            {
                string word = s.substr(i, j - i);
                if (find(wordDict.begin(), wordDict.end(), word) != wordDict.end() && dp[i])
                {
                    dp[j] = true;
                }
            }
        }
        return dp[s.size()];
    }
};

原理思路:

        物品可以重复使用,填充背包,可以看出是一个完全背包问题。如果不知道背包问题,可以看我前面的文章动态规划:0-1背包、完全背包问题 | 详细原理解释 | 代码及优化(C++)_Cosmoshhhyyy的博客-CSDN博客_c++代码优化工具,这里具体就不再讲解了。这里就简单讲讲思路。

        构建dp数组,dp数组的含义是s中下标 j 之前包含 j 的字符串能否被字典中组成,然后初始化,显然dp[0] 的时候为true,因为为空的时候不用组成就是符合条件的,其他位置为false,为后面递推公式做准备。

        遍历顺序一定要先遍历背包,因为此题是需要考虑组成顺序的,不同顺序组成的单词肯定不同。虽然归为完全背包问题,但是我感觉其实和一般的完全背包在思路上还是有点不同的,并不完全是完全背包问题。

        我更想理解为是两个指针,一个为 j ,一个为 i ,j 在 i 之前,如果 i - j 的片段可由字典组成,同时dp[i] 为 true,也就是片段之前的字符串也可由字典组成,那么肯定最后 dp[s.size()] 为 true的话,说明符合条件呗,感觉这样说比用完全背包解释此题好理解多了。

你可能感兴趣的:(LeetCode,leetcode,c++,算法,动态规划)