Word Break [dp, j as first loop]
139.Word Break
Dynamic Programming
String
Hash Table
Problem Statement:
Given a string s and a dictionary of strings wordDict, return true if s can be segmented into a space-separated sequence of one or more dictionary words.
Example:
Input:
s = "leetcode"wordDict = ["leet","code"]
→
Output:
trueReturn true because "leetcode" can be segmented as "leet code"
Algorithm:
- Use DP array where dp[i] represents if s[0,i] can be segmented
- For each index j, try to break string at every previous index i
- Check if substring exists in dictionary and previous segment is valid
- Use HashSet for O(1) word lookup
Complexity:
Time: O(n³) due to substring | Space: O(n) for DP array
Java Solution:
public boolean wordBreak(String s, List wordDict) {
// DP array where dp[i] means s[0:i] can be segmented
boolean[] dp = new boolean[s.length()];
// Convert dictionary to HashSet for O(1) lookup
Set word = new HashSet<>(wordDict);
// Process each ending position
for (int j = 0; j < s.length(); j++) {
// Check if entire substring is a word
if (word.contains(s.substring(0, j + 1))) {
dp[j] = true;
continue;
}
// Try to break string at each previous position
for (int i = j; i >= 1; i--) {
String sub = s.substring(i, j + 1);
// Check if current substring is word and previous part is valid
if (word.contains(sub) && dp[i - 1])
dp[j] = true;
}
}
return dp[s.length() - 1];
}
Python Solution:
def wordBreak(self, s: str, wordDict: List[str]) -> bool:
# DP array where dp[i] means s[0:i] can be segmented
dp = [False] * len(s)
word_set = set(wordDict)
# Process each ending position
for j in range(len(s)):
# Check if entire substring is a word
if s[:j + 1] in word_set:
dp[j] = True
continue
# Try to break string at each previous position
for i in range(j, 0, -1):
sub = s[i:j + 1]
if sub in word_set and dp[i - 1]:
dp[j] = True
break
return dp[-1]
C++ Solution:
bool wordBreak(string s, vector& wordDict) {
// DP array where dp[i] means s[0:i] can be segmented
vector<bool> dp(s.length());
unordered_set word_set(wordDict.begin(), wordDict.end());
// Process each ending position
for (int j = 0; j < s.length(); j++) {
// Check if entire substring is a word
if (word_set.count(s.substr(0, j + 1))) {
dp[j] = true;
continue;
}
// Try to break string at each previous position
for (int i = j; i >= 0; i--) {
string sub = s.substr(i, j - i + 1);
if (word_set.count(sub) && dp[i - 1]) {
dp[j] = true;
break;
}
}
}
return dp.back();
}