力扣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];
    }
};
相关推荐
风筝在晴天搁浅1 小时前
剑指Offer LCR 143.子结构判断
算法
咖啡八杯1 小时前
GoF设计模式——装饰模式
java·算法·设计模式·装饰器模式
装不满的克莱因瓶1 小时前
实现矩阵的点积:从数学原理到 NumPy 实战
人工智能·线性代数·算法·机器学习·矩阵·numpy
HZ·湘怡1 小时前
树 的定义 与 性质
算法·
梦想的颜色1 小时前
Docker 入门指南:从零开始掌握容器化技术
运维·服务器·vscode·python·算法·docker·云原生
cpp_25011 小时前
P10109 [GESP202312 六级] 工作沟通
数据结构·c++·算法·题解·洛谷·gesp六级
吴可可1231 小时前
CAD二次开发中多段线定点分割技巧
算法
ʚ希希ɞ ྀ1 小时前
全排列 --- 回溯
算法·leetcode·深度优先
玉树临风ives1 小时前
atcoder ABC 460 题解
数据结构·c++·算法