Word Break Problem in DSA Typescript - Time & Space Complexity
We want to understand how the time needed to solve the Word Break Problem changes as the input grows.
Specifically, how does checking if a string can be split into dictionary words scale with string length?
Analyze the time complexity of the following code snippet.
function wordBreak(s: string, wordDict: Set): boolean {
const dp = new Array(s.length + 1).fill(false);
dp[0] = true;
for (let i = 1; i <= s.length; i++) {
for (let j = 0; j < i; j++) {
if (dp[j] && wordDict.has(s.substring(j, i))) {
dp[i] = true;
break;
}
}
}
return dp[s.length];
}
This code checks if the string can be split into words from the dictionary using dynamic programming.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Nested loops where for each position in the string, we check all previous positions.
- How many times: Outer loop runs n times (string length), inner loop runs up to n times, so roughly n x n checks.
As the string length grows, the number of checks grows roughly with the square of the length.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 100 checks |
| 100 | About 10,000 checks |
| 1000 | About 1,000,000 checks |
Pattern observation: Doubling the string length roughly quadruples the work.
Time Complexity: O(n^3)
This means the time grows roughly with the cube of the string length due to substring extraction and dictionary lookups.
[X] Wrong: "The solution runs in linear time because it just loops through the string once."
[OK] Correct: There is a nested loop inside, so for each character, it checks all previous positions, making it slower than linear.
Understanding this time complexity helps you explain your approach clearly and shows you know how nested loops affect performance.
"What if we used a Trie to check dictionary words instead of substring checks? How would the time complexity change?"
Practice
s and a dictionary of words wordDict?Solution
Step 1: Understand the problem goal
The Word Break Problem asks if the entire stringscan be split into parts where each part is a word from the dictionarywordDict.Step 2: Clarify what is being checked
It is not about substrings not in the dictionary or exact matches only, but about segmentingsfully into dictionary words.Final Answer:
Ifscan be segmented into a sequence of dictionary words -> Option DQuick Check:
Word Break = segment string into dictionary words [OK]
- Thinking it checks for partial substrings only
- Confusing exact match with segmentation
- Assuming reversed words are considered
Solution
Step 1: Identify correct parameter types
The function should take a stringsand an array of stringswordDictrepresenting the dictionary words.Step 2: Identify correct return type
The function returns a boolean indicating ifscan be segmented or not.Final Answer:
function wordBreak(s: string, wordDict: string[]): boolean -> Option BQuick Check:
Correct params and boolean return [OK]
- Using wrong parameter types
- Returning wrong data type
- Swapping parameter order
function wordBreak(s: string, wordDict: string[]): boolean {
const wordSet = new Set(wordDict);
const dp = Array(s.length + 1).fill(false);
dp[0] = true;
for (let i = 1; i <= s.length; i++) {
for (let j = 0; j < i; j++) {
if (dp[j] && wordSet.has(s.substring(j, i))) {
dp[i] = true;
break;
}
}
}
return dp[s.length];
}
console.log(wordBreak("leetcode", ["leet", "code"]));Solution
Step 1: Understand the dynamic programming approach
The code uses a boolean arraydpwheredp[i]is true if substrings[0..i-1]can be segmented into dictionary words.Step 2: Trace the example input "leetcode"
"leet" and "code" are in the dictionary. The code finds "leet" at start and setsdp[4]true, then "code" from index 4 to 8 setsdp[8]true. So finaldp[s.length]is true.Final Answer:
true -> Option CQuick Check:
DP finds full segmentation = true [OK]
- Confusing substring indices
- Not breaking inner loop after true
- Misunderstanding dp array meaning
function wordBreak(s: string, wordDict: string[]): boolean {
const wordSet = new Set(wordDict);
const dp = Array(s.length).fill(false);
dp[0] = true;
for (let i = 1; i <= s.length; i++) {
for (let j = 0; j < i; j++) {
if (dp[j] && wordSet.has(s.substring(j, i))) {
dp[i] = true;
break;
}
}
}
return dp[s.length];
}Solution
Step 1: Check dp array initialization
The dp array is created with sizes.length, but it needs to bes.length + 1to include the base case dp[0].Step 2: Understand consequences of wrong dp size
Accessingdp[s.length]will be out of bounds, causing runtime errors or incorrect results.Final Answer:
dp array size is incorrect; should be s.length + 1 -> Option AQuick Check:
dp size must cover 0 to s.length indices [OK]
- Using dp array of wrong size
- Confusing Set with array for dictionary
- Incorrect substring index order
s = "applepenapplepenapple" and dictionary wordDict = ["apple", "pen"], what is the minimum number of segments needed to fully segment s into dictionary words?Solution
Step 1: Break down the string into dictionary words
The string is "applepenapplepenapple". The dictionary words are "apple" and "pen". The string can be segmented as "apple" + "pen" + "apple" + "pen" + "apple".Step 2: Count the segments
There are 5 segments total: apple, pen, apple, pen, apple.Final Answer:
5 -> Option AQuick Check:
Count dictionary words in segmentation = 5 [OK]
- Counting characters instead of words
- Missing repeated segments
- Assuming fewer segments possible
Ready to prove it?
Pass the test and this pattern moves unknown
