package com.example.lettcode.dailyexercises;
import java.util.ArrayList;
import java.util.List;
/**
* @Class WordBreak
* @Description 139. 单词拆分
* 给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,
* 判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。
* <p>
* 说明:
* 拆分时可以重复使用字典中的单词。
* 你可以假设字典中没有重复的单词。
* <p>
* 示例 1:
* 输入: s = "leetcode", wordDict = ["leet", "code"]
* 输出: true
* 解释: 返回 true 因为 "leetcode" 可以被拆分成 "leet code"。
* <p>
* 示例 2:
* 输入: s = "applepenapple", wordDict = ["apple", "pen"]
* 输出: true
* 解释: 返回 true 因为 "applepenapple" 可以被拆分成 "apple pen apple"。
* 注意你可以重复使用字典中的单词。
* <p>
* 示例 3:
* 输入: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"]
* 输出: false
* @Author
* @Date 2020/6/25
**/
public class WordBreak {
}
/**
* 解法1:利用递归和回溯,超时
*/
public static boolean wordBreak(String s, List<String> wordDict) {
return subWordBreak(s, wordDict, 0);
}
private static boolean subWordBreak(String s, List<String> wordDict, int start) {
// 结束条件,当字符串s遍历结束,说明字符串s全部匹配,
if (start == s.length()) return true;
for (int end = start + 1; end <= s.length(); end++) {
// 如果s[start,end) 匹配wordDict中的某个单词,并且s[end,..] 也可以拆分;
if (wordDict.contains(s.substring(start, end)) && subWordBreak(s, wordDict, end)) {
return true;
}
}
// 没有找到匹配的单词
return false;
}
/**
* 解法2:动态规划,时间复杂度为O(n^2)
*/
public static boolean wordBreak(String s, List<String> wordDict) {
int len = s.length();
// 状态dp[i]表示前i个字符组成的字符串能否被字典中的word来组成。
// 状态转换方式:dp[i] = dp[0..j] && (s.sub(j.i) 是否由wordDict组成) 同时成立时,dp[i]=true
// 动态规划dp[i]的值并不一定非得由dp[i-1]决定,也可以是受dp[0]..dp[i-1]值影响
Boolean[] dp = new Boolean[len + 1];
dp[0] = true;
for (int i = 1; i <= len; i++) {
dp[i] = false;
// 如果s[0..j) 是由wordDict 组成,并且 s[j..i]也由wordDict的某个单词构成
// 说明dp[i] 是可以由wordDict组成的
for (int j = 0; j < i; j++) {
if (dp[j] && wordDict.contains(s.substring(j, i))) {
dp[i] = true;
break;
}
}
}
return dp[len];
}
// 测试用例
public static void main(String[] args) {
String s = "leetcode";
List<String> wordDict = new ArrayList<>();
// "leet", "code"
wordDict.add("leet");
wordDict.add("code");
boolean ans = wordBreak(s, wordDict);
System.out.println("demo01 result:" + ans);
s = "applepenapple";
wordDict = new ArrayList<>();
// ["apple", "pen"]
wordDict.add("apple");
wordDict.add("pen");
ans = wordBreak(s, wordDict);
System.out.println("demo02 result:" + ans);
s = "catsandog";
wordDict = new ArrayList<>();
//["cats", "dog", "sand", "and", "cat"]
wordDict.add("cats");
wordDict.add("dog");
wordDict.add("sand");
wordDict.add("and");
wordDict.add("cat");
ans = wordBreak(s, wordDict);
System.out.println("demo03 result:" + ans);
}