力扣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];
    }
};
相关推荐
To_OC4 小时前
LC 1 两数之和:面试第一道必考题,暴力解法直接被面试官 pass
javascript·算法·leetcode
鱼鱼不愚与8 小时前
《原来如此 | 第01期:为什么导航软件能预测红绿灯倒计时?》
算法
复杂网络13 小时前
论最小 Agent 计算机的形态
算法
kisshyshy1 天前
🍦 雪糕、食堂、火车厢:三幅漫画吃透栈、队列与链表
javascript·算法
猿人谷1 天前
不只是 CPU 阈值:STAR 如何用 GAT + Transformer 做容器级自动扩缩容?
人工智能·算法
复杂网络2 天前
Stable Diffusion 视觉大模型微调技术深度调研
算法
复杂网络2 天前
基于 Stable Diffusion 架构的视觉大模型代表性工作与原理深度解析
算法
MrZhao4002 天前
Agent Loop 如何用 Hook 扩展:权限、日志与工具拦截
算法
MrZhao4002 天前
Agent 为什么需要 Skills:别把所有知识都塞进 system prompt
算法