leetcode 139: 单词拆分

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);
}
原文地址:https://www.cnblogs.com/fyusac/p/13194037.html