LeetCode 140 Word Break II

Given a string s and a dictionary of words dict, add spaces in s to construct a sentence where each word is a valid dictionary word.

Return all such possible sentences.

For example, given
s = "catsanddog",
dict = ["cat", "cats", "and", "sand", "dog"].

A solution is ["cats and dog", "cat sand dog"].

方法一:Runtime: 15 ms beats 47.49% of javasubmissions.

	public List<String> wordBreak3(String s, Set<String> wordDict) {
		Map<String, ArrayList<String>> map = new HashMap<>();
		return wordBreakHelper(s, wordDict, map);
	}

	public List<String> wordBreakHelper(String s, Set<String> dict, Map<String, ArrayList<String>> memo) {
		if (memo.containsKey(s)) return memo.get(s);
		ArrayList<String> result = new ArrayList<>();
		int n = s.length();
		if (n <= 0) return result;
		for (int len = 1; len <= n; ++len) {
			String prefix = s.substring(0, len);
			if (dict.contains(prefix)) {
				if (len == n) {
					result.add(prefix);
				} else {
					String suffix = s.substring(len);
					List<String> tmp = wordBreakHelper(suffix, dict, memo);
					for (String item : tmp) {
						item = prefix + " " + item;
						result.add(item);
					}
				}
			}
		}
		memo.put(s, result);
		return result;
	}

参考:http://www.jiuzhang.com/solutions/word-break-ii/

方法二:

Runtime: 6 ms beats 94.01% of javasubmissions.

思路:判断s.substring(0,i)如果是字典里的word,如果是,递归判断s.substring(i)的字符串分解情况。

具体过程如下:

1.判断s.substring(0,i)如果是字典里的word,那么就继续判断后截儿字符串s.substring( i )的情况;

2.判断后截儿字符串s.substring( i )是否可分解,以及s.substring( i )分解的字符串集合,如果s.substring(i,i+x)是字典里的word,那么就判断s.substring(x)是否可分解,以及获取从x位之后s.substring( x )分解的字符串集合;

3.重复2步骤,判断s.substring( x )是否可分解,以及s.substring( x)分解的字符串集合。在分解的过程中,我们会获取到invalid[x]的值,因此可知s.substring( x )是否可分解。当第1步骤中递归中的for循环到s.substring(0,x)的时候,如果invalid[x]已经是true,可确定x之后的字符串是不可分的,那就直接跳过继续往后判断了;

最初的时候,我们是设定invalid[x]为false的,即我们是不确定invalid[x]的值(invalid[x]初始化也为false),因此不知道后截儿字符串是否可分,所以我们继续往下判断。

另外,s.substring(x)的break方式有多种,也许没有,只要有一种,就是可破解的。所以初始化possible=false,递归函数返回值为boolean 类型的flag,只要有一个flag=true,就证明s.substring(x) can be breaked.

设置invalid[x]变量,表示s自i位起之后的字符串即s.substring(x)是否可分解,这个方法的速度之所以快,就是因为有这个变量的存在,可以避免重复判断无效的s.substring(x).


	public List<String> wordBreak4(String s, Set<String> wordDict) {
		List<String> res = new ArrayList<>();
		wordBreak(s, 0, wordDict, "", new boolean[s.length() + 1], res);
		return res;
	}

	/**
	 * Helper function for Leetcode 140. Word Break II.
	 *
	 * @param s        string to break
	 * @param left     start point
	 * @param wordDict dictionary
	 * @param prev     previous word found
	 * @param invalid  invalid[i] means whether [i, s.length()) is unbreakable
	 * @param res      list to store results
	 * @return true if s.substring(left) is breakable.
	 */
	private boolean wordBreak(String s, int left, Set<String> wordDict, String prev, boolean[] invalid, List<String> res) {
		if (left == s.length()) {// Base case: successfully moved to the end, add result to the list.
			res.add(prev.trim());//去掉prev首尾的空格
			return true;
		}
		boolean possible = false;// whether s.substring(left) is breakable
		for (int i = left + 1; i <= s.length(); i++) {// find whether [left, i) is valid
			if (invalid[i]) continue;// if s.substring(i) is unbreakable, continue
			String sub = s.substring(left, i);
			if (wordDict.contains(sub)) {
				boolean flag = wordBreak(s, i, wordDict, prev.concat(" ").concat(sub), invalid, res);
				possible = flag || possible;// as long as at least one valid substring [i, end), possible is true
			}
		}
		invalid[left] = !possible;// update invalid array
		return possible;
	}


参考https://discuss.leetcode.com/topic/50114/java-beating-95-13-with-explanation-dfs-memoization-to-avoid-tle

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值