题目:
给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。
说明:
拆分时可以重复使用字典中的单词。
你可以假设字典中没有重复的单词。
示例 1:
输入: s = “leetcode”, wordDict = [“leet”, “code”]
输出: true
解释: 返回 true 因为 “leetcode” 可以被拆分成 “leet code”。
示例 2:
输入: s = “applepenapple”, wordDict = [“apple”, “pen”]
输出: true
解释: 返回 true 因为 “applepenapple” 可以被拆分成 “apple pen apple”。
注意你可以重复使用字典中的单词。
示例 3:
输入: s = “catsandog”, wordDict = [“cats”, “dog”, “sand”, “and”, “cat”]
输出: false
错误的代码,27/36
思路:队列中储存每一个循环中当前的start值加上单词的len
失败在:“aaaaaaaaaaaaaaaaaaa”[“a”,“aa”,“aaa”…]for循环超时了
class Solution {
失败在//输入为:“aaaaaaaaaaaaaaaaaaaa”;
public boolean wordBreak(String s, List<String> wordDict) {
if(wordDict.size()==0) return false;
if(only(s))return true;//用来对付“aaaaaaaaaaaaaaaaaaaa”; 不过这个有弊端而且不完善,玩一下罢了
int start=0;
Queue<Integer> squeue=new LinkedList<>();
int size=0;
do{
if(!squeue.isEmpty()){//isEmpty()
start=squeue.poll();
}
for(int i=0;i<wordDict.size();i++){
String str=wordDict.get(i);
if(helper(s,start,start+str.length(),str)){//参数对应好
if(start+str.length()==s.length()) return true;
int newstart=start+str.length(); //start=start+str.length();该start值已经变了,会影响同一for循环中的其他判断所以要new
squeue.offer(newstart);
}
}
}while(!squeue.isEmpty());//; //enmpty()
return false;
}
public boolean helper(String s,int l,int r,String str){
if(r>s.length()) return false; //必须有
String str1=s.substring(l,r);
return str1.equals(str);
}
public boolean only(String s){
int i=0;
char a=s.charAt(0);//
for(int j=0;j<s.length();j++){
i=s.charAt(j)-a;
if(i!=0) return false;
}
return true;
}
}
自己的DP:
思路类似硬币:在dp[i]时,假如我能取这个硬币(输入给的字符串s截取的部分==Llist中相同长度的str),我取之后,dp[i-str.len]是否为true,是的话就可以取。
class Solution {
public boolean wordBreak(String s, List<String> wordDict) {
boolean[] dp=new boolean[s.length()+1];
Arrays.fill(dp,false);//似乎可以不用fill,因为默认值为false; //Arrays,有s记住了。
dp[0]=true;
for(int i=1;i<s.length()+1;i++){
for(int j=0;j<wordDict.size();j++){ // for(String str: dict) 这样更加简洁
String str=wordDict.get(j);
if(str.length()>i)continue; //错误:str.length
if(dp[i-str.length()]){
if(s.substring(i-str.length(),i).equals(str)){ //错误:if(s.substring(i-str.length() +1
dp[i]=true; // 优化:要明白一个循环的目的,目的达到了就推出循环,不要让变数产生。
//break; //优化
}
}
}
}
return dp[s.length()]; //错误:dp[s.length()]
}
}
if(s.substring(i-str.length(),i).equals(str)) //错误:if(s.substring(i-str.length() +1
针对索引要不要±1,可以考虑用[0]或者[len-1]来确定。
return dp[s.length()]; //错误:dp[s.length()]
对数组定义时要注意了,最大的索引时定义时的-1;在DP中要特别注意,因为经常返回的是最后一个
学习,代码来自leetcode.discuss
public class Solution {
public boolean wordBreak(String s, Set<String> dict) {
boolean[] f = new boolean[s.length() + 1];
f[0] = true;
//Second DP
for(int i=1; i <= s.length(); i++){// 循环的目的就是要确认f[i]的值,所以i还是得在前面
for(int j=0; j < i; j++){
if(f[j] && dict.contains(s.substring(j, i))){
f[i] = true;
break;
}
}
}
return f[s.length()];
}
}