当前位置: 首页 > news >正文

动态规划经典题解:单词拆分(LeetCode 139)

动态规划经典题解:单词拆分(LeetCode 139)

一、题目描述

原题链接
单词拆分

题目大意
给定一个非空字符串 s 和一个包含非空单词的列表 wordDict,判断 s 是否可以被空格拆分为一个或多个在字典中出现的单词。字典中的单词可以重复使用。字典中无重复单词。
示例
输入:s = “leetcode”, wordDict = [“leet”, “code”]
输出:true(解释:“leetcode” 可拆分为 “leet code”)

输入:s = “applepenapple”, wordDict = [“apple”, “pen”]
输出:true(解释:“applepenapple” 可拆分为 “apple pen apple”)

输入:s = “catsandog”, wordDict = [“cats”, “dog”, “sand”, “and”, “cat”]
输出:false

二、解题思路

核心思想:动态规划(DP)
本题的核心是判断字符串的「前缀是否可拆分」,通过动态规划逐步推导所有前缀的可行性,避免重复计算。
1. 状态定义
定义 dp[i] 表示:字符串 s 的前 i 个字符组成的子串 s[0…i-1] 是否能被字典中的单词拼接而成。例如:dp[4] 对应 s 的前 4 个字符 s[0…3](即 “leet”)是否可拆分。
2. 状态转移方程
对于每个位置 i(从 1 到 s.size()),遍历字典中的每个单词 word:若 word 的长度 len ≤ i(保证子串存在);且 s 中以 i 为结尾、长度为 len 的子串(即 s.substr(i-len, len))等于 word;且 dp[i-len] 为 true(说明 s 的前 i-len 个字符可拆分);则 dp[i] = true(前 i 个字符可拆分)。
3. 初始化
dp[0] = true:表示空字符串可被拆分(基础条件,用于推导后续前缀。例如,当 word 恰好等于 s[0…len-1] 时,dp[len] = dp[0] && (子串匹配))。
4. 最终结果
dp[s.size()]:表示整个字符串 s 是否可拆分。

三、代码实现

#include <vector>
#include <string>
using namespace std;class Solution {
public:bool wordBreak(string s, vector<string>& wordDict) {int n = s.size();// dp[i]:前i个字符是否可拆分vector<bool> dp(n + 1, false);// 初始化:空字符串可拆分dp[0] = true;// 遍历所有前缀长度(从1到n)for (int i = 1; i <= n; ++i) {// 遍历字典中的每个单词for (const string& word : wordDict) {int word_len = word.size();// 条件1:单词长度不超过当前前缀长度if (word_len <= i) {// 条件2:子串匹配 + 前i-word_len个字符可拆分if (s.substr(i - word_len, word_len) == word && dp[i - word_len]) {dp[i] = true;// 无需继续遍历其他单词,直接跳出内层循环break;}}}}// 返回整个字符串是否可拆分return dp[n];}
};

四、边界情况与测试用例

边界情况
s 为空字符串:题目规定 s 非空,无需处理;
wordDict 中存在与 s 完全匹配的单词:如 s = “a”, wordDict = [“a”],dp[1] = dp[0] && (s.substr(0,1) == “a”) = true;单词长度大于 s 长度:如 s = “a”, wordDict = [“aa”],内层循环条件 word_len <= i 不满足,dp[1] 保持 false。

测试用例验证
示例 1:s = “leetcode”, wordDict = [“leet”, “code”]
i=4:单词 “leet” 长度 4 ≤ 4,s.substr(0,4) = “leet” 匹配,dp[0] = true → dp[4] = true;i=8:单词 “code” 长度 4 ≤ 8,s.substr(4,4) = “code” 匹配,dp[4] = true → dp[8] = true;
返回 true。

示例 2:s = “catsandog”, wordDict = [“cats”, “dog”, “sand”, “and”, “cat”]
前 7 个字符 “catsand” 可拆分为 “cats + and”(dp[7] = true);但 i=9(整个字符串长度)时,遍历所有单词:
“dog” 长度 3 ≤ 9,s.substr(6,3) = “dog” 匹配,但 dp[6] = false;其他单词均不满足条件 → dp[9] = false;
返回 false。

五、 类似题目

LeetCode 140. 单词拆分 II;
LeetCode 472. 连接词

http://www.dtcms.com/a/589016.html

相关文章:

  • Softmax 与 Sigmoid:深入理解神经网络中的两类激活函数
  • OpenCV(二十一):图像的放大与缩小
  • 【Datawhale25年11月组队学习:hello-agents+Task1学习笔记】
  • 从零开始:如何搭建你的第一个简单的Flask网站
  • Babylon.js材质冻结的“双刃剑“:性能优化与IBL环境冲突的深度解析
  • 力扣1611——使整数变为 0 的最少操作次数(简单易懂版)
  • uni-app PDA焦点录入实现
  • uniapp接入安卓端极光推送离线打包
  • 宁波模板建站定制网站建立企业网站的流程
  • hotspot vm 参数解析
  • Titiler无需切片即可实现切片形式访问影像
  • 通过数学变换而不是组装来构造软件
  • Week 24: 深度学习补遗:Vision Transformer (ViT) 复现
  • 做的好的茶叶网站wordpress百度百科
  • paho mqtt c 指定tls加密算法安全套件
  • 2025年下半年网络工程师基础知识真题及答案解析
  • 网站怎么做电脑系统下载文件安装wordpress素锦
  • 解析 CodexField 五大核心模块:构建下一代链上内容资产基础设施
  • 如何在命令行启用Dev-C++的调试模式?
  • handler机制原理面试总结
  • 人工智能备考——1.2.1-1.2.5总结
  • SQL50+Hot100系列(11.9)
  • vue-router相关理解
  • 怎么做才能设计出好的网站网站充值这么做
  • Qt QWidget点击信号全解析:从基础交互到高级实战
  • 【Spark】操作记录
  • Vue 项目实战《尚医通》,医院详情菜单与子路由,笔记17
  • Kettle 小白入门指南:从A表到B表的数据清洗实战
  • 莱芜正规的企业建站公司东莞专业网站建设公司
  • 尝试性解读 Hopper 和 BlackWell 架构的硬件缓存一致性及其深远影响