题目描述:
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"
.
自己写的一个算法超时了:
public class Solution { public boolean wordBreak(String s, Set<String> wordDict) { int n=s.length(); boolean[][] dp=new boolean[n][n]; for(int l=1;l<=n;l++){ for(int i=0;i<n-l+1;i++){ loop:for(int j=i;j<i+l;j++){ if(wordDict.contains(s.substring(i, j+1))) dp[i][j]=true; else{ for(int k=i;k<j;k++){ if(dp[i][k]&&dp[k+1][j]){ dp[i][j]=true; continue loop; } } dp[i][j]=false; } } } } return dp[0][n-1]; } }正确的AC算法如下:
自上而下的备忘录法:
public class Solution { private HashMap<String, Boolean> map = new HashMap<>(); public boolean wordBreak(String s, Set<String> wordDict) { if (s.length() == 0) return true; if (map.containsKey(s)) return map.get(s); for (int i = 0; i <= s.length(); i++) { String prefix = s.substring(0, i); if (wordDict.contains(prefix)) { if (wordBreak(s.substring(i), wordDict)) { map.put(s, true); return true; } } } map.put(s, false); return false; } }这个算法还可以优化:
记下来dict中单词的最大长度,这样就不用查询每一个单词都从头查到尾了。
上面是用的map来记录,这里一个set和一个数组来代替。
public class Solution { public boolean wordBreak(String s, Set<String> wordDict) { if (s == null || s.length() == 0) { return false; } int maxLength = maxLengthStr(wordDict); return dfs(s, 0, wordDict, new boolean[s.length()], maxLength); } private boolean dfs(String s, int idx, Set<String> wordDict, boolean[] unbreakable, int maxLength) { if (idx >= s.length()) { return true; } else if (unbreakable[idx]) { return false; } else { int end = Math.min(idx + maxLength, s.length()); for (int i = idx + 1; i <= end; i++) { if (wordDict.contains(s.substring(idx, i))) { if (dfs(s, i, wordDict, unbreakable, maxLength)) { return true; } } } unbreakable[idx] = true; return false; } } private int maxLengthStr(Set<String> wordDict) { int max = 0; for (String str : wordDict) { max = Math.max(max, str.length()); } return max; } }自下而上的dp:
public class Solution { public boolean wordBreak(String s, Set<String> wordDict) { if (s == null || s.isEmpty()) { return false; } int n = s.length(); boolean[] breakable = new boolean[n + 1]; breakable[0] = true; for (int i = 1; i <= n; i++) { for (int j = i - 1; j >= 0; j--) { if (breakable[j] && wordDict.contains(s.substring(j, i))) { breakable[i] = true; break; } } } return breakable[n]; } }