【LeetCode】Word Break && Word Break II

本文介绍了WordBreak问题的三种解法:逐字匹配、迭代字典优化与动态规划。通过对比,展示了动态规划方法的优势,并提供了WordBreak II问题的解决思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Word Break:

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".

解法1:

将字典里的每个单词取出与字符串进行匹配,成功则截取此部分,进入迭代

[java]  view plain copy
  1. public class Solution  
  2. {  
  3.     public boolean wordBreak(String s, Set<String> dict)  
  4.     {  
  5.         if (s == null || dict == null || dict.isEmpty() || s.equals(""))  
  6.             return false;  
  7.         return find(s, dict);  
  8.   
  9.     }  
  10.   
  11.     public boolean find(String s, Set<String> dict)  
  12.     {  
  13.         if (s.equals(""))  
  14.             return true;  
  15.         boolean flag = false;  
  16.         for (String str : dict) {  
  17.             if (s.startsWith(str)) {  
  18.                 String ss;  
  19.                 ss = s.substring(str.length(), s.length());  
  20.                 flag = find(ss, dict);  
  21.             }  
  22.             if (flag)  
  23.                 return true;  
  24.         }  
  25.         return false;  
  26.   
  27.     }  

超时


解法2:

保存一个迭代字典hash,里面是已经验证的可以构成s前缀的字符串。每次迭代将hash中的字符串与dict两两组合并判断是否是s的前缀,是的话加入新的hash。长度超过s则直接跳过。

false条件:hash为空,即上一轮的hash和dict没有构成新的字符串。

[java]  view plain copy
  1. public boolean wordBreak(String s, Set<String> dict)  
  2.     {  
  3.         if (s == null || dict == null || dict.isEmpty())  
  4.             return false;  
  5.         if (s.equals(""))  
  6.             return true;  
  7.         HashSet<String> hs = new HashSet<String>();  
  8.         for (String str : dict) {  
  9.             if(s.equals(str))  
  10.                 return true;  
  11.             if (s.startsWith(str))  
  12.                 hs.add(str);  
  13.         }  
  14.         return find(s, hs, dict);  
  15.   
  16.     }  
  17.   
  18.     public boolean find(String s, Set<String> check, Set<String> dict)  
  19.     {  
  20.         HashSet<String> hash = new HashSet<String>();  
  21.         for (String ss : check)  
  22.             for (String str : dict) {  
  23.                 if (ss.length() + str.length() > s.length())  
  24.                     continue;  
  25.                 String newStr = ss + str;  
  26.                 if (newStr.equals(s))  
  27.                     return true;  
  28.                 if (s.startsWith(newStr))  
  29.                     hash.add(newStr);  
  30.             }  
  31.         if (hash.isEmpty())  
  32.             return false;  
  33.         return find(s, hash, dict);  
  34.     }  

解法3:

创建boolean数组dp[],dp[i]==true则表明字符串s中的第i位可以达到

最优子结构:如果第i-1位可以构成,只用判断后面是否可以构成s。

出口条件:当dp[s.length-1]==true时,说明可以构成

public boolean wordBreak(String s, Set<String> dict)
	{
		boolean[] dp = new boolean[s.length()];
		for (int i = 0; i < s.length(); i++) {
			if (i > 0 && !dp[i - 1])
				continue;
			for (String str : dict) {
				if (i + str.length() > s.length())
					continue;
				if (str.equals(s.substring(i, i + str.length()))) {
					dp[i + str.length() - 1] = true;
				}
				if (dp[s.length() - 1]) {
					return true;
				}
			}
		}

		return false;
	}

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"].

public List<String> wordBreak(String s, Set<String> dict)
	{
		boolean[] dp = new boolean[s.length()];
		ArrayList<Integer>[] a =(ArrayList<Integer>[]) new ArrayList[s.length()];
		for (int i = 0; i < s.length(); i++)
			a[i] = new ArrayList<Integer>();

		ArrayList<String> arr = new ArrayList<String>();

		dp[0] = true;
		for (int i = 0; i < s.length(); i++) {
			if (i > 0 && !dp[i - 1])
				continue;

			for (String str : dict) {
				if (i + str.length() > s.length())
					continue;
				if (s.substring(i, i + str.length()).equals(str)) {
					dp[i + str.length() - 1] = true;
					a[i].add(i + str.length());
				}
			}
		}
		foo(a, 0,new StringBuffer(""), s, arr);
		return arr;
	}

	public void foo(ArrayList<Integer>[] a, int i, StringBuffer ss, String s,
			ArrayList<String> arr)
	{
		for (Integer k : a[i]) {
			if(i==0)
				ss=new StringBuffer("");
			ss.append(s.substring(i, k) + " ");
			if (k==s.length())
				arr.add(ss.substring(0, ss.length() - 1));
			else
				foo(a, k, ss, s, arr);
				
		}

	}

DP记录分割点对每个分割点i建立链表,保存所有可以达到的位置。最后dfs构建字符串。

注意每次i=0时,字符串要清空



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值