代码随想录|动态规划|26单词拆分

leetcode:139. 单词拆分 - 力扣(LeetCode)

题目

给定一个非空字符串 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

思路

(1)dp[i]: 字符串长度为i的话,dp[i]为true,表示可以拆分为一个或多个在字典中出现的单词。

(2)如果确定dp[j] 是true,且 [j, i] 这个区间的子串出现在字典里,那么dp[i]一定是true。(j < i )。

递推公式为:

if([j,i] && dp[j]==true){

dp[i]=true;}

(3)这里怎么看排列顺序呢?

 

 (4)dp[0]一定为true,不然后面根据递推公式会一直为false。

#include <vector>
#include <unordered_set>
using namespace std;

class Solution
{
public:
    /**
     * 使用动态规划方法解决单词拆分问题
     *
     * @param s 待拆分的字符串
     * @param wordDict 单词字典,包含可以用于拆分的单词
     * @return bool 表示字符串s是否可以由字典中的单词拆分
     *
     * 该函数通过动态规划的方式判断字符串s是否可以由字典中的单词连续拆分。
     * 动态规划数组dp用于记录字符串的每一个位置是否可以被字典中的单词拆分。
     * unordered_set用于存储单词字典,以提高查找效率。
     */
    bool wordBreak(string s, vector<string> &wordDict)
    {
        // 将单词字典转换为unordered_set,提高查找效率
        unordered_set<string> wordSet(wordDict.begin(), wordDict.end());
        // 初始化动态规划数组,大小为字符串长度+1,初始值均为false
        vector<bool> dp(s.size() + 1, false);
        // 设置初始条件,空字符串视为可以拆分
        dp[0] = true;

        // 遍历字符串s的所有子串,从1到s.size()逐步构建dp数组(j表示背包)
        for (int j = 1; j <= s.size(); j++)
        {
            // 对于每个j,向前检查所有可能的子串(i表示物品)
            for (int i = 0; i < j; i++)
            {
                // 提取子串s[i:j]
                string word = s.substr(i, j - i);
                // 如果该子串在字典中找到,且dp[i]为true,则说明s[0:j]可以拆分
                if (wordSet.find(word) != wordSet.end() && dp[i] == true)
                {
                    // 更新dp数组
                    dp[j] = true;
                    // 找到一种拆分方法即可,跳出循环
                    break;
                }
            }
        }
        // 返回最终的拆分结果
        return dp[s.size()];
    }
};

总结

从小到大逐渐找s的子串,看子串是不是数组里面的元素。

参考资料

代码随想录 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值