Word Break Problem in DSA C - 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.
bool wordBreak(char* s, char** wordDict, int wordDictSize) {
int n = strlen(s);
bool dp[n+1];
dp[0] = true;
for (int i = 1; i <= n; i++) {
dp[i] = false;
for (int j = 0; j < i; j++) {
if (dp[j] && isInDict(s + j, i - j, wordDict, wordDictSize)) {
dp[i] = true;
break;
}
}
}
return dp[n];
}
// Helper function checks if substring s of length len is in wordDict
bool isInDict(char* s, int len, char** wordDict, int wordDictSize) {
for (int k = 0; k < wordDictSize; k++) {
if (strlen(wordDict[k]) == len && strncmp(s, wordDict[k], len) == 0) {
return true;
}
}
return false;
}
This code checks if the input 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; inner loop runs up to n times for each outer iteration.
- Additional work: For each substring checked, we scan the dictionary to find a match.
As the string length grows, the number of checks grows roughly with the square of the length times the dictionary size.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 * 10 * wordDictSize checks |
| 100 | About 100 * 100 * wordDictSize checks |
| 1000 | About 1000 * 1000 * wordDictSize checks |
Pattern observation: Operations grow roughly with the square of the input length multiplied by dictionary size.
Time Complexity: O(n^2 * m * k)
This means the time grows roughly with the square of the string length (n), times the number of words in the dictionary (m), times the average length of dictionary words (k).
[X] Wrong: "The solution runs in linear time because it just loops through the string once."
[OK] Correct: The code uses nested loops and checks many substrings against the dictionary, so the work grows much faster than just one pass.
Understanding this time complexity helps you explain how your solution scales and shows you can analyze nested loops and dictionary lookups clearly.
"What if we used a hash set for the dictionary to check words in constant time? How would the time complexity change?"
Practice
s and a dictionary of words wordDict?Solution
Step 1: Understand the problem statement
The Word Break Problem asks if the entire stringscan be split into parts where each part is a word in the dictionary.Step 2: Compare options with the problem
Ifscan be segmented into a space-separated sequence of one or more dictionary words correctly describes this segmentation into dictionary words. Other options describe different checks.Final Answer:
Ifscan be segmented into a space-separated sequence of one or more dictionary words -> Option BQuick Check:
Word Break Problem = segmentation check [OK]
- Thinking it checks for substring presence only
- Confusing exact match with segmentation
- Assuming palindrome check
Solution
Step 1: Understand parameter types for the Word Break function
The stringsis a character array, sochar s[]orchar *sworks. The dictionary is an array of strings, sochar *wordDict[]is correct. The size is an integer.Step 2: Check each option
int wordBreak(char s[], char *wordDict[], int wordDictSize); matches the correct signature:int wordBreak(char s[], char *wordDict[], int wordDictSize);int wordBreak(char *s, char *wordDict, int wordDictSize); useschar *wordDictwhich is incorrect for array of strings. void wordBreak(char s[], char wordDict[], int size); useschar wordDict[]which is incorrect for array of strings. int wordBreak(char **s, char **wordDict, int wordDictSize); useschar **swhich is incorrect for a single string.Final Answer:
int wordBreak(char s[], char *wordDict[], int wordDictSize); -> Option AQuick Check:
Function prototype with string and array of strings = int wordBreak(char s[], char *wordDict[], int wordDictSize); [OK]
- Using char wordDict[] instead of array of strings
- Using char **s for input string
- Wrong return type or missing parameters
char *dict[] = {"leet", "code"};
int result = wordBreak("leetcode", dict, 2);
printf("%d", result);Assuming wordBreak returns 1 if segmentation is possible, else 0.Solution
Step 1: Analyze the input string and dictionary
The string is "leetcode" and dictionary contains "leet" and "code".Step 2: Check if string can be segmented
"leetcode" can be split as "leet" + "code", both in dictionary, so segmentation is possible.Final Answer:
1 -> Option AQuick Check:
"leetcode" segmented as "leet" + "code" = 1 [OK]
- Assuming partial match is enough
- Confusing return values
- Ignoring dictionary contents
int wordBreak(char *s, char **wordDict, int wordDictSize) {
int len = strlen(s);
int dp[len+1];
dp[0] = 1;
for (int i = 1; i <= len; i++) {
dp[i] = 0;
for (int j = 0; j < i; j++) {
if (dp[j] && strncmp(s+j, wordDict[i], i-j) == 0) {
dp[i] = 1;
break;
}
}
}
return dp[len];
}Solution
Step 1: Understand the nested loop and string comparison
The inner loop checks substrings from index j to i. It should compare with wordDict[j], not wordDict[i].Step 2: Identify the incorrect array index usage
Using wordDict[i] is wrong because i goes up to length of s, which may exceed wordDictSize and is unrelated to dictionary indexing.Final Answer:
Using wordDict[i] instead of wordDict[j] in strncmp -> Option CQuick Check:
Index in dictionary should match substring start index [OK]
- Mixing loop variables for dictionary access
- Not initializing dp array correctly
- Ignoring return statement
s = "applepenapple" and dictionary wordDict = ["apple", "pen"], which approach correctly solves the Word Break Problem using dynamic programming in C?Solution
Step 1: Understand dynamic programming approach
We create a boolean dp array where dp[i] is true if substrings[0..i-1]can be segmented into dictionary words.Step 2: Check all substrings ending at each position
For each position i, check all j < i where dp[j] is true and substrings[j..i-1]is in dictionary. If yes, set dp[i] true.Step 3: Return dp[length of s]
If dp at the end is true, the string can be segmented.Final Answer:
Use a boolean dp array where dp[i] is true ifs[0..i-1]can be segmented, then check all substrings ending at i -> Option DQuick Check:
DP boolean array with substring checks = Use a boolean dp array where dp[i] is true ifs[0..i-1]can be segmented, then check all substrings ending at i [OK]
- Using recursion without memo causing timeout
- Sorting dictionary does not help segmentation
- Stack approach is incorrect for this problem
Ready to prove it?
Pass the test and this pattern moves unknown
