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

自己写的一个算法超时了:

public class Solution {
    public boolean wordBreak(String s, Set<String> wordDict) {
        int n=s.length();
        boolean[][] dp=new boolean[n][n];
    	for(int l=1;l<=n;l++){
    		for(int i=0;i<n-l+1;i++){
    			loop:for(int j=i;j<i+l;j++){
    				if(wordDict.contains(s.substring(i, j+1)))
    					dp[i][j]=true;
    				else{
    					for(int k=i;k<j;k++){
    						if(dp[i][k]&&dp[k+1][j]){
    							dp[i][j]=true;
    							continue loop;
    						}			
    					}
    					dp[i][j]=false;
    				}
    			}
    		}
    	}
    	return dp[0][n-1];
    }
}
正确的AC算法如下:

自上而下的备忘录法:

public class Solution {
    private HashMap<String, Boolean> map = new HashMap<>();
    public boolean wordBreak(String s, Set<String> wordDict) {
        if (s.length() == 0) return true;
        if (map.containsKey(s)) return map.get(s);
        for (int i = 0; i <= s.length(); i++) {
            String prefix = s.substring(0, i);
            if (wordDict.contains(prefix)) {
                if (wordBreak(s.substring(i), wordDict)) {  
                    map.put(s, true);
                    return true;
                }
            }
        }
        map.put(s, false);
        return false;
    }
}
这个算法还可以优化:

记下来dict中单词的最大长度,这样就不用查询每一个单词都从头查到尾了。

上面是用的map来记录,这里一个set和一个数组来代替。

public class Solution {
	public boolean wordBreak(String s, Set<String> wordDict) {
	    if (s == null || s.length() == 0) {
	        return false;
	    }
	    int maxLength = maxLengthStr(wordDict);
	    return dfs(s, 0, wordDict, new boolean[s.length()], maxLength);
	}
	
	private boolean dfs(String s, int idx, Set<String> wordDict, boolean[] unbreakable, int maxLength) {
	    if (idx >= s.length()) {
	        return true;
	    } else if (unbreakable[idx]) {
	        return false;
	    } else {
	        int end = Math.min(idx + maxLength, s.length());
	        for (int i = idx + 1; i <= end; i++) {
	            if (wordDict.contains(s.substring(idx, i))) {
	                if (dfs(s, i, wordDict, unbreakable, maxLength)) {
	                    return true;
	                }
	            }
	        }
	        unbreakable[idx] = true;
	        return false;
	    } 
	}
	
	private int maxLengthStr(Set<String> wordDict) {
	    int max = 0;
	    for (String str : wordDict) {
	        max = Math.max(max, str.length());
	    }
	    return max;
	}
}
自下而上的dp:

public class Solution {
    public boolean wordBreak(String s, Set<String> wordDict) {
        if (s == null || s.isEmpty()) {
            return false;
        }

        int n = s.length();
        boolean[] breakable = new boolean[n + 1];
        breakable[0] = true;
        for (int i = 1; i <= n; i++) {
            for (int j = i - 1; j >= 0; j--) {
                if (breakable[j] && wordDict.contains(s.substring(j, i))) {
                    breakable[i] = true;
                    break;
                }
            }
        }
        return breakable[n];
    }
}


你可能感兴趣的:(java,LeetCode,动态规划)