Input:
s = "leetcode", wordDict = ["leet","code"]
Output:
true
Explanation: Return true because "leetcode" can be segmented as "leet code".
Example 2:
1
2
3
4
5
6
Input:
s = "applepenapple", wordDict = ["apple","pen"]
Output:
true
Explanation: Return true because "applepenapple" can be segmented as "apple pen apple".
Note that you are allowed to reuse a dictionary word.
Example 3:
1
2
3
4
Input:
s = "catsandog", wordDict = ["cats","dog","sand","and","cat"]
Output:
false
This is very similar to method 1, but we can also loop on wordDict to do the break.
As dictionary size is smaller than string s, we can loop over all the words in dict. For word w in dictionary, we can check if w exists in string and look for remaining string to break.
In method 1, if the size of the dictionary is very large, the time is bad. Instead we can solve the problem in O(n^2) time (n is the length of the string).
The recursive solution has many subproblems that are repeating at various stage of the recursion. For example, for string abcd the recursion tree will look like
1
2
3
4
5
abcd
/\\ bcd cd d
/\| cd d d
We can see that subproblems for “cd” is repeating twice. So, we can cache the solution.
⏰ Time complexity: O(n^3 + m). Where n - length of string s and m - number of words in dict. We have n paths in dfs, and then we loop from idx + 1 to n, and then we create substring which takes O(n) time, hence overall O(n^3), plus O(m) time to make set.
🧺 Space complexity: O(n + m) - for recursive state, and m for storing values in set.
We can convert previous approach into bottom-up DP. Lets dp[i] represents if substring(0,i) is breakable. Now, for each substring, we will check and fill in the dp[i].
publicclassSolution {
publicbooleanwordBreak(String s, List<String> wordDict) {
int n = s.length();
if(n == 0) {
returnfalse;
}
Set<String> set =new HashSet<>(wordDict);
boolean[] dp =newboolean[n + 1];
// an empty string can always be formed // without using any word from wordDict dp[0]=true;
for(int i = 1; i <= n; i++){
for(int j = 0; j < i; j++){
if(dp[j]&& set.contains(s.substring(j, i))){
dp[i]=true;
break;
}
}
}
return dp[n];
}
}