力扣HOT100(51) 动态规划-单词拆分

动态规划核心思路(一句话讲透)

dp[i]表示:字符串s的前i个字符(也就是s[0..i-1]),能不能被字典里的单词拼接出来

对于每个位置i,我们只需要找一个分割点j0 ≤ j < i),满足两个条件:

  1. j个字符已经可以被拆分:dp[j] == true
  2. ji的子串s[j..i-1],正好在字典里

只要存在这样一个j,那么dp[i]就等于true

完整解题步骤 --哈希表 dp 遍历双循环一个i负责变量s 一个j负责遍历0-i的分割点 看所有分割的可能

1. 预处理字典:转成哈希集合

为了快速判断一个子串是否在字典里,我们先把wordDict转成unordered_set,这样查找的时间复杂度是 O (1),比直接遍历数组快很多。

2. 初始化 dp 数组

  • 数组长度:s.size() + 1(因为要表示前 0 个到前 n 个字符,共 n+1 种状态)
  • 所有元素初始化为false
  • 边界条件dp[0] = true
    • 前 0 个字符就是空串,空串不需要任何单词就能拼接出来,所以是合法的
    • 这是所有推导的基础,没有这个条件,整个 dp 数组都会是 false

3. 遍历计算 dp 数组

  • 外层循环:i1s.size(),表示当前要判断前i个字符能不能被拆分
  • 内层循环:j0i-1,枚举所有可能的分割点
    • 如果dp[j] == true(前 j 个字符合法),并且子串s.substr(j, i-j)在字典里
    • 那么dp[i] = true,直接 break 内层循环(只要找到一个合法的分割点就行)

4. 返回结果

dp[s.size()]就是整个字符串能不能被拆分的答案。

cpp 复制代码
class Solution {
public:
    bool wordBreak(string s, vector<string>& wordDict) {
        //转为哈希表集合
        unordered_set<string> wordSet;
        for(string word : wordDict){
            wordSet.insert(word);
        }

        //初始化dp数组
        //dp[i]表示前i个字符能不能被拆分
        int n  = s.size();
        vector<bool> dp(n+1,false);//n+1个数 初始值都是false
        dp[0] = true;//边界条件

        //遍历
        for(int i = 1;i<=n;i++){
            //分割点
            for(int j = 0;j<i;j++){
                if(dp[j] && wordSet.count(s.substr(j,i-j))){
                    dp[i] = true;
                    break;
                }
            }
        }

        return dp[n];
    }
};
相关推荐
伊玛目的门徒3 小时前
试用leetcode之典中典 二数之和问题
java·算法·leetcode
Jerry3 小时前
LeetCode 226. 翻转二叉树
算法
想做小南娘,发现自己是女生喵4 小时前
【无标题】
数据结构·算法
Kx_Triumphs6 小时前
HDU4348 To the moon(主席树区间修改模板)
算法·题解
旖-旎6 小时前
《LeetCode647 回文子串 || LeetCode 5 最长回文子串》
c++·算法·leetcode·动态规划·哈希算法
轻颂呀8 小时前
约瑟夫环问题
算法
科技大视界9 小时前
投资AI项目,传统尽调不够用了——李章虎律师拆解算法、数据、算力三大雷区
人工智能·算法·数据挖掘
郝学胜-神的一滴9 小时前
算法实战:最小k个数——大顶堆的优雅解法
开发语言·数据结构·c++·python·程序人生·算法·排序算法
Irissgwe10 小时前
算法滑动窗口
数据结构·算法