Leetcode:139. 单词拆分

题目:
给定一个非空字符串 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()];
    }
}

猜你喜欢

转载自blog.csdn.net/Fishandbearspaw/article/details/89031710