重点1:
判断字符串s是否在List<String>中,即实现类似python中in方法
将List转为Set,然后用Set的contains方法
List转Set:
Set<String> set = new HashSet(wordDict);
实现:
1 public boolean check(String s, List<String> wordDict){ 2 Set<String> set = new HashSet(wordDict); 3 if(set.contains(s)) 4 return true; 5 else 6 return false; 7 }
解题:
方法1:递归(部分测试用例会超时)
递归出口:空字符串默认可以分为wordDict
递归式:f(s[0..n]) = check(s[0,i-1]) && f(s[i..n]) 注意与动态规划的区别,动态规划要求第i项与第i-1项或者i-2项有递推关系
即 s[0..n]可以分为wordDict 当且仅当 s[0,i-1]在wordDict中 && s[i,n]可以分为wordDict
1 public boolean wordBreak(String s, List<String> wordDict) { 2 boolean flag=false; 3 int n = s.length(); 4 if (s.equals("")) 5 return true; 6 for(int i = 1; i <n+1; i++){ 7 if(check(s.substring(0,i),wordDict) && wordBreak(s.substring(i,n), wordDict)){ 8 flag=true; 9 break; 10 }else{ 11 flag=false; 12 } 13 } 14 return flag; 15 }
方法2:动态规划
1、一般问有几种方案而不问具体方案是什么时考虑动态规划
2、很多时候题目中的问题就可以用来建立状态数组
例如本题,问s是否可以拆分为wordDict ---> dp[n+1] 表示s[0..n]是否可以拆分为wordDict
3、建立状态转移方程
由于要填写长度为n+1的状态表dp中的每一个值dp[i]
所以找dp[i]与前面项的关系:dp[i]为true当(1)dp[i-1] && check(s[i-1..i]) 或者(2)dp[i-2] && check(s[i-2..i])……或dp[0] && check(s[0..i]),因此用j来做指针,得到
dp[i] = dp[j] && check(s[j,i]) 即s[0,i] = s[0,j]+s[j,i] 观察到动态规划转移方程中前后项是有联系的
4、初始状态
dp[0] =true 空字符串默认可以分为wordDict
1 public boolean wordBreak(String s, List<String> wordDict) { 2 boolean[] dp = new boolean[s.length()+1];//dp[i]表示s.substring(0,i)能否被划分成wordDict的单词 3 dp[0] = true; 4 for(int i = 1; i<=s.length(); i++){ 5 for(int j = 0; j<i; j++){ 6 if(dp[j]&&check(s.substring(j,i),wordDict)){ 7 dp[i] = true; 8 break; 9 } 10 } 11 } 12 return dp[s.length()]; 13 }