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

LeetCode 139. Word Break 题解

LeetCode 139. Word Break 题解

题目描述

给你一个字符串 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

解题思路

这是一个经典的动态规划问题,类似于"完全背包"问题。

状态定义:

  • dp[i] 表示字符串 s 的前 i 个字符是否可以被拆分成字典中的单词

状态转移方程:

  • dp[i] = True,如果存在 j < i,使得 dp[j] = True 且 s[j:i] 在字典中

初始条件:

  • dp[0] = True(空字符串可以被拆分)

代码实现

方法一:动态规划

def wordBreak(s, wordDict): word_set = set(wordDict) n = len(s) # dp[i] 表示前 i 个字符是否可以被拆分 dp = [False] * (n + 1) dp[0] = True for i in range(1, n + 1): for j in range(i): # 如果前 j 个字符可以拆分,且 s[j:i] 在字典中 if dp[j] and s[j:i] in word_set: dp[i] = True break return dp[n]

方法二:优化内层循环

def wordBreak(s, wordDict): word_set = set(wordDict) n = len(s) # 找到字典中最长单词的长度 max_len = max(len(word) for word in wordDict) if wordDict else 0 dp = [False] * (n + 1) dp[0] = True for i in range(1, n + 1): # 只需要检查长度不超过 max_len 的子串 for j in range(max(0, i - max_len), i): if dp[j] and s[j:i] in word_set: dp[i] = True break return dp[n]

复杂度分析

  • 时间复杂度:O(n² × m),其中 n 是字符串长度,m 是字典中最长单词的长度
  • 空间复杂度:O(n),dp 数组的空间

BFS 解法

也可以使用 BFS 解决:

from collections import deque def wordBreak(s, wordDict): word_set = set(wordDict) n = len(s) visited = [False] * n queue = deque([0]) while queue: start = queue.popleft() if visited[start]: continue visited[start] = True for end in range(start + 1, n + 1): if s[start:end] in word_set: if end == n: return True queue.append(end) return False

测试案例

# 测试案例 1 assert wordBreak("leetcode", ["leet", "code"]) == True # 测试案例 2 assert wordBreak("applepenapple", ["apple", "pen"]) == True # 测试案例 3 assert wordBreak("catsandog", ["cats", "dog", "sand", "and", "cat"]) == False # 测试案例 4 assert wordBreak("", ["a"]) == True # 测试案例 5 assert wordBreak("a", []) == False

总结

本题是动态规划的经典应用,也是字符串拆分问题的基础。

关键点:

  • 状态定义:dp[i] 表示前 i 个字符是否可以被拆分
  • 状态转移:枚举所有可能的拆分点
  • 优化:限制内层循环的范围

通过本题可以深入理解动态规划在字符串问题中的应用。

http://www.jsqmd.com/news/550349/

相关文章:

  • 告别LoRA测试烦恼:Jimeng LoRA单次加载、多版本快速切换指南
  • 广州市米古曼皮具有限公司,广东高端女包/皮具厂,布局广州等地 - 十大品牌榜
  • 2026年职业资格考前辅导与技能实训平台推荐:昇职学堂西医/考研/护师网络课程与资料服务公司精选 - 品牌推荐官
  • DIY USB3.0集线器翻车实录:GL3523芯片的USB3.0死活不认,问题到底出在哪儿?
  • OpenClaw多模型切换:ollama-QwQ-32B与本地小模型协同工作流
  • 从JIT到AOT再到Cuvil编译器:Python AI推理部署演进史(2024年Q2最新Gartner评估报告核心结论首发)
  • 如何在Windows系统无缝运行移动应用?开源工具APK Installer的颠覆性方案
  • 如何让任何显卡都能体验AI超分辨率?OptiScaler技术深度解析与实战指南
  • Umi-OCR性能调优实战指南:老旧系统文字识别效率提升方案
  • 影刀RPA冷门技巧:多工具联动的工作流搭建方法
  • 2026最新包包一手货源推荐!广州优质皮具厂家/直销工厂权威榜单 - 十大品牌榜
  • (新手)Linux 输入子系统实战教程 —— 02设备信息查询 + 输入事件读取(阻塞 / 非阻塞模式)
  • C#ListView数据绑定组件
  • 告别接线板!用ESim电工仿真APP在手机上搞定低压电工证实操练习(附星三角启动电路教程)
  • 大模型学习避坑指南:小白也能轻松入门并收藏这份高效进阶路线
  • Z-Image-GGUF完整教程:阿里通义文生图模型从安装到出图
  • 算一算(一)经典Miller补偿极点
  • 使用ComfyUI可视化工作流构建NLP-StructBERT语义搜索应用
  • LMX2595实战:手把手教你配置JESD204B时钟与SYSREF(含相位同步避坑指南)
  • 企业级文档数字化:Umi-OCR离线光学字符识别工具全流程落地指南
  • Genome Biology:启动子设计赋予水稻多重抗病性
  • macOS极速体验OpenClaw:nanobot镜像免配置调试技巧
  • 2026最新广东广州皮具推荐!国内优质皮具生产/批发厂商权威榜单发布 - 十大品牌榜
  • 用Python+OpenCV给斗地主做个‘外挂’:手把手教你写个桌面记牌器(附源码)
  • 如何使用Rufus创建Windows 11启动盘:完整配置指南与TPM绕过方案
  • 恶劣天候激光雷达点云模拟技术研究进展与实战应用
  • 2026最新高端女包直播供应链推荐!广东广州优质服务商权威榜单 - 十大品牌榜
  • 看完就会:2026年必备一键生成论文工具榜单,免费高效产出合规稿
  • 3分钟掌握Chrome文本替换插件:让任何网页变成你的可编辑文档
  • 品牌方必看:小红书舆情监测工具怎么选?2026年小红书舆情监测工具对比测评