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

老专家个人网站廊坊网站建设企业

老专家个人网站,廊坊网站建设企业,网站开发专业大学,企业网站制作的软件🚀 LeetCode 热题 139:单词拆分(Word Break)| 动态规划全解析细节陷阱 📌 题目描述 给你一个字符串 s 和一个字符串列表 wordDict 作为字典。请判断 s 是否可以由字典中出现的单词拼接成。 说明:不要求字典…

🚀 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
解释:可以拼接成 "apple pen apple",可以重复使用 wordDict 中的单词。

🎯 示例 3:

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

💡 解题思路一:动态规划(DP)

我们定义一个布尔类型的一维数组 dp[i] 表示 s[0:i] 这个子串是否可以由字典中的单词组成。

🧱 状态定义:

我们用一个布尔数组 dp[i] 表示:

从字符串的起始位置(下标 0)到位置 i 的子串 s[0:i] 是否可以被成功拆分成一个或多个字典中的单词。

注意:这里的 i 是长度,不是下标(下标是 i-1)。


✅ 状态转移方程:

dp[i] = true,若存在 j,使得 dp[j] == true 且 s[j:i] 在 wordDict 中

也就是说,如果前面某个位置 j 之前的子串可以被拼出,并且 s[j:i] 在字典中,那 dp[i] 就可以设置为 true

✅ 初始条件:

dp[0] = true  // 空字符串可视为已完成

💻 Go 实现代码(动态规划)

func wordBreak(s string, wordDict []string) bool {wordSet := make(map[string]bool)for _, word := range wordDict {wordSet[word] = true}dp := make([]bool, len(s)+1)dp[0] = truefor i := 1; i <= len(s); i++ {for j := 0; j < i; j++ {if dp[j] && wordSet[s[j:i]] {dp[i] = truebreak}}}return dp[len(s)]
}

🔍 注意点 & 边界问题解析

✅ 注意 1:不要和子串的下标混淆

  • dp[i] 代表的是前 i 个字符构成的子串(即 s[0:i]),而不是下标 i 的字符。
  • 所以判断子串是否在字典中时,要写 s[j:i],而不是 s[j:i+1]

✅ 注意 2:字典查找效率

使用 map[string]bool 构造一个哈希集合 wordSet 替代数组,可以让查找从 O(n) 降到 O(1),大幅提升效率:

wordSet := make(map[string]bool)
for _, word := range wordDict {wordSet[word] = true
}

✅ 注意 3:剪枝优化(提前结束)

只要在内层循环找到一个合法切割位置,就可以直接 break,节省无效循环。


✅ 注意 4:空字符串与空字典

  • s = "",返回 true,空字符串默认可以拆分(dp[0]=true)。
  • wordDict = [],返回 false,无单词可用无法拼出。

🌈 图解理解

假设输入:

s = "applepenapple"
wordDict = ["apple", "pen"]

我们依次维护 dp 状态:

i子串 s[0:i]能否拆分dp[i]
0“”true
5“apple”true
8“applepen”true
13“applepenapple”true

🧠 更深层的理解(背后的思想)

本题其实可以抽象为:

把一个字符串切成若干段,看这些段是否全都能在字典中找到。

也可以类比为:

一个人从字符串左端起跳,只能跳到在字典中出现的词结尾位置,问能否跳到终点。

所以动态规划是处理“前缀是否可达”这种问题的最优解。


⏳ 复杂度分析

类型复杂度
时间复杂度O(n²)
空间复杂度O(n)
  • n 是字符串长度。
  • 时间复杂度主要来自两层循环和切片操作。
  • 使用哈希集合加速查找操作。

🧠 解题思路二:记忆化搜索(DFS + 记忆化)

从起始位置出发,尝试所有可能的切割位置,只要有一个可行就返回 true

为了防止重复计算,使用 map[int]bool 进行记忆。


💻 Go 实现代码(记忆化 DFS)

func wordBreak(s string, wordDict []string) bool {wordSet := make(map[string]bool)for _, word := range wordDict {wordSet[word] = true}memo := make(map[int]bool)var dfs func(int) booldfs = func(start int) bool {if start == len(s) {return true}if val, ok := memo[start]; ok {return val}for end := start + 1; end <= len(s); end++ {if wordSet[s[start:end]] && dfs(end) {memo[start] = truereturn true}}memo[start] = falsereturn false}return dfs(0)
}

🔍 两种方法对比

方法优点缺点
动态规划性能稳定,逻辑清晰,适合面试高频实现上可能略显冗长
记忆化 DFS更贴近人类思考方式,递归直观有栈溢出风险,依赖剪枝优化

✅ 总结

  • 本题是经典的字符串 + 动态规划题型。
  • 动态规划和记忆化搜索都值得掌握!
  • 实际编码中推荐使用动态规划,执行效率更高。

🎁 加分思考

  • 如果要求输出所有可能的拆分方式?
  • 如果字典非常大,如何优化查找?(使用 Trie 前缀树)

🌟 更多高频算法题持续更新中…

欢迎点赞 👍、收藏 ⭐、评论 💬、关注 🧠,支持我继续输出优质 LeetCode 题解!💻📘📌


http://www.dtcms.com/wzjs/560834.html

相关文章:

  • 免费网站服务器安全百度seo提交
  • 企业简介的网站怎么做百度ip地址
  • 南昌购物网站开发网站建设模块方案书
  • 网络营销网站源码怎么把一个网站设置成首页
  • asp.net做网站next 主题wordpress
  • 贵州seo技术查询台州网站优化公司
  • 中山网站建设联系电话广点通都有哪些平台投放
  • 网站收录软件表格里怎么做链接网站
  • 聊城那里有做网站网站服务器租用 配置
  • 网站广告位制作权威发布型舆情回应以事实性
  • 多语言外贸企业网站源码wordpress 自动标签插件
  • 深圳做高端网站建设公司郑州网站开发网站开发
  • 网站页面在线设计虎扑体育网体育
  • photoshop做网站设计浏览器兄弟懂的拿走不谢2021
  • 网站建设的上市公司c 可以做网站吗
  • 漳州网站优化东莞气缸东莞网站建设
  • 智能建网站wordpress 机械模板下载地址
  • 免费不收费用网站网站公众号小程序开发公司
  • 南宁网站建设招聘禁止显示网站目录
  • 辽源做网站公司seo插件wordpress
  • 怎么做免费的网站商城wap网站制作
  • 黄石网站设计公司哪些购物网站做的比较简洁有品质
  • 临沂城乡建设管理局网站哪个网站是可以做书的
  • 研究网站平台建设工作动态装修工人自己接单的app
  • 空投注册送币网站怎么做关键词seo优化软件
  • 备案二级域名分发北京道路优化
  • 外国人搞笑做视频网站青白江做网站的公司
  • 注册网站邮箱发送的验证网页无法打开凡客怎么了
  • 商会网站怎么做组织建设内容
  • 门户网站app开发建筑人才网兼职小时工