目录
- 目录
- 前言
- 题目
- DFS
- 动态规划
前言
过完年回来状态一直就是懒懒散散的,之前想写的年终总结也一直再拖沓。所以,从今天起找回之前的状态,每日的工作计划没完成就不能休息。今天的任务中有两道LeetCode题目,其中一道动态规划的题目稍微难一点,这里记录一下解题过程。
题目
Given a string s and a dictionary of words dict, determine if s can be segmented into a space-separated sequence of one or more dictionary words.
For example, given
s = "leetcode",
dict = ["leet", "code"].
Return true because “leetcode” can be segmented as “leet code”.
原文链接:Work Break
DFS
开始看到这个题目的时候,我也没想到用动态规划,也许是好久没有练习动态规划题目的原因了。但是,每个题目都有它最容易想到的方法,因此我开始是想通过DFS+剪枝来解决这道题目。
有了思路,代码很自然的写出来,代码如下:
public class Solution {
public boolean wordBreak(String s, Set<String> dict) {
return dfsWordBreak(s, dict, 0);
}
private boolean dfsWordBreak(String s, Set<String> dict, int bt) {
if (bt >= s.length()) {
return true;
}
for (String word : dict) {
int len = word.length();
if (bt + len <= s.length() && s.substring(bt, bt + len).equals(word)) {
boolean res = dfsWordBreak(s, dict, bt + len);
if (res) {
return true;
}
}
}
return false;
}
}
用DFS思路最怕的就是超时,果不其然,代码提交到LeetCode,确实是超时了。
(PS:吐槽一下GFW,现在上LeetCode都不稳定,我竟然需要翻那啥才能稳定的提交代码)
动态规划
既然DFS不行,这样的题目就只能考虑动态规划了。动态规划是一种算法思路, 它是利用空间存储历史信息使得未来需要历史信息时不需要重新计算,从而达到降低时间复杂度,是一种用空间换取时间的方法。
- 既然动态规划需求存储历史信息,那我们首先应该确认我们要存储的历史信息。这里我用boolean location[i]表示到字符串s的第i个字符时,是否可以用dict中的词来表示。
- 然后,我们假设我们有location[0…i-1]的结果,那么location[i]的值应该是:location[i] = location[j] && s.substring(j, i + 1) in dict,其中j属于[0…i - 1]。这也就是我们所说的状态方程。
有了状态方程,我们很容易就可以写出动态规划的AC代码了,注意一下边界条件即可。
public class Solution {
public boolean wordBreak(String s, Set<String> dict) {
if (s == null || s.length() == 0) {
return true;
}
// initial boolean array
boolean[] locs = new boolean[s.length() + 1];
for (int i = 0; i < locs.length; i ++) {
locs[i] = false;
}
locs[0] = true;
// dynamic programming
for (int i = 1; i < locs.length; i ++) {
locs[i] = false;
for (int j = 0; j < i; j ++) {
if (locs[j] && dict.contains(s.substring(j, i))) {
locs[i] = true;
break;
}
}
}
return locs[locs.length - 1];
}
}
时间: 2024-10-07 05:36:42