☰
动态规划解决力扣单词拆分问题
2026/10/31 7:58:23 网站建设 项目流程

1. 题目解析与核心思路

力扣第86题"单词拆分"(实际应为139题)是一个经典的字符串处理与动态规划结合的问题。题目要求我们判断给定字符串s是否能被拆分为字典wordDict中一个或多个单词的组合。例如:

  • 输入:s = "leetcode", wordDict = ["leet", "code"]
  • 输出:true(因为"leetcode"可以拆分为"leet"+"code")

这个问题的难点在于需要考虑所有可能的拆分方式,而暴力枚举所有可能性会导致指数级的时间复杂度。我在实际解题中发现,动态规划是解决这类问题的金钥匙。

1.1 动态规划解法原理

定义dp[i]表示字符串s的前i个字符(s[0..i-1])能否被拆分成字典中的单词。状态转移方程为:

dp[i] = dp[j] && check(s[j..i−1]),其中0 ≤ j < i

check(s[j..i−1])表示子串s[j..i−1]是否出现在字典中。这个方程的意思是:如果前j个字符可以拆分(dp[j]=true),且剩下的子串也在字典中,那么前i个字符就可以拆分。

关键提示:初始化dp[0]=true,表示空字符串可以被拆分。这是所有推导的基础条件。

2. 详细实现与优化技巧

2.1 基础实现代码(Python)

def wordBreak(s, wordDict): word_set = set(wordDict) n = len(s) dp = [False] * (n + 1) dp[0] = True for i in range(1, n + 1): for j in range(i): if dp[j] and s[j:i] in word_set: dp[i] = True break return dp[n]

这个实现的时间复杂度是O(n²),空间复杂度是O(n)。我在力扣上测试时发现,对于中等长度的字符串(n≤100)表现良好,但当n达到1000时就会超时。

2.2 性能优化技巧

  1. 字典预处理:将wordDict转为集合,查询时间从O(m)降为O(1)
  2. 剪枝策略:只检查长度不超过max_len的子串,max_len是字典中最长单词的长度
  3. 记忆化搜索:使用DFS+记忆化可以避免重复计算

优化后的代码:

def wordBreak(s, wordDict): word_set = set(wordDict) max_len = max(len(word) for word in wordDict) if wordDict else 0 n = len(s) dp = [False] * (n + 1) dp[0] = True for i in range(1, n + 1): start = max(0, i - max_len) if max_len else 0 for j in range(start, i): if dp[j] and s[j:i] in word_set: dp[i] = True break return dp[n]

3. 边界条件与特殊测试用例

在实际编码面试中,这些边界条件常常是考察重点:

  1. 空字符串:

    • s = "", wordDict = ["a"] → 应返回true(空字符串可以被拆分)
  2. 字典为空:

    • s = "a", wordDict = [] → 应返回false
  3. 重复前缀:

    • s = "aaaaaaa", wordDict = ["aaaa", "aaa"] → 需要正确处理重叠匹配
  4. 无法拆分但部分匹配:

    • s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"] → 应返回false

避坑指南:我曾在一个case上卡了半小时,后来发现是忘记处理字典中存在空字符串的情况。建议在代码开头显式检查if "" in word_set: return s == ""

4. 算法扩展与变种问题

4.1 返回所有可能的拆分方案

这是原题的进阶版本(力扣140题),需要DFS回溯:

def wordBreak(s, wordDict): word_set = set(wordDict) memo = {} def dfs(s): if s in memo: return memo[s] if not s: return [""] res = [] for word in word_set: if s.startswith(word): for substr in dfs(s[len(word):]): res.append(word + (" " + substr if substr else "")) memo[s] = res return res return dfs(s)

4.2 字典单词可重复使用

原题已经允许重复使用字典中的单词,但如果限制使用次数,问题会变得更复杂,需要引入额外的状态记录。

5. 实际应用场景

这种字符串拆分算法在现实中有广泛应用:

  1. 自然语言处理:分词处理(特别是像中文这样没有空格分隔的语言)
  2. 编译器设计:词法分析阶段识别关键字和标识符
  3. 密码破解:尝试组合字典中的单词生成可能的密码
  4. 智能输入法:预测和补全用户输入的单词

我在开发一个IDE插件时就用到类似算法,用于自动检测代码中的拼写错误。通过建立专业术语字典,可以准确识别出"getLenght"这样的拼写错误(正确应为"getLength")。

6. 不同语言的实现差异

虽然算法思想相同,但不同语言的实现有细微差别:

Java实现特点:

public boolean wordBreak(String s, List<String> wordDict) { Set<String> wordSet = new HashSet<>(wordDict); boolean[] dp = new boolean[s.length() + 1]; dp[0] = true; for (int i = 1; i <= s.length(); i++) { for (int j = 0; j < i; j++) { if (dp[j] && wordSet.contains(s.substring(j, i))) { dp[i] = true; break; } } } return dp[s.length()]; }

JavaScript实现注意点:

function wordBreak(s, wordDict) { const wordSet = new Set(wordDict); const dp = new Array(s.length + 1).fill(false); dp[0] = true; for (let i = 1; i <= s.length; i++) { for (let j = 0; j < i; j++) { if (dp[j] && wordSet.has(s.substring(j, i))) { dp[i] = true; break; } } } return dp[s.length]; }

性能提示:在JS中,Set的has方法比数组的includes快得多,这是为什么我们要先将wordDict转为Set。

7. 复杂度分析与优化极限

对于长度为n的字符串和包含m个单词的字典:

  1. 时间复杂度:

    • 基础DP:O(n²)
    • 带max_len优化:O(n×L),其中L是字典中最长单词长度
  2. 空间复杂度:

    • O(n)用于存储dp数组
    • O(m)用于存储wordSet

经过测试,当n=1000时,优化前后的运行时间差异可以达到10倍以上。我建议在面试时先给出基础解法,然后主动提出优化思路,这能展示你的算法思维深度。

8. 常见错误与调试技巧

根据我在力扣讨论区看到的常见错误:

  1. 错误初始化:

    • 忘记设置dp[0]=true
    • 错误:dp = [False]*n(应该是n+1)
  2. 索引混淆:

    • 把s[j:i]写成s[j:i+1]
    • 循环条件写成for i in range(n)(应该是range(1,n+1))
  3. 字典处理不当:

    • 直接使用wordDict而没转为集合
    • 没有考虑字典中有空字符串的情况

调试时可以打印dp数组来验证:

print([(i, val) for i, val in enumerate(dp)])

9. 进阶学习建议

要彻底掌握这类问题,我推荐:

  1. 系统学习动态规划:

    • 先掌握背包问题、最长公共子序列等经典DP问题
    • 理解状态定义和转移方程的设计思路
  2. 相关题目练习:

    • 力扣472:连接词(单词拆分的加强版)
    • 力扣140:单词拆分II(输出所有可能)
    • 力扣139:回文分割(类似思路)
  3. 实际项目应用:

    • 尝试实现一个简单的拼写检查器
    • 开发一个代码自动补全的简易版本

我在准备算法面试时,会把同类问题集中练习。比如连续刷5道字符串DP问题,就能明显感受到解题模式的重复性。单词拆分这类问题看似简单,但能很好考察候选人对DP和字符串处理的综合掌握程度。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询