Watch 10 video solutions for Word Break II, a hard level problem involving Array, Hash Table, String. This walkthrough by NeetCode has 345,872 views views. Want to try solving it yourself? Practice on FleetCode or read the detailed text solution.
Given a string s and a dictionary of strings wordDict, add spaces in s to construct a sentence where each word is a valid dictionary word. Return all such possible sentences in any order.
Note that the same word in the dictionary may be reused multiple times in the segmentation.
Example 1:
Input: s = "catsanddog", wordDict = ["cat","cats","and","sand","dog"] Output: ["cats and dog","cat sand dog"]
Example 2:
Input: s = "pineapplepenapple", wordDict = ["apple","pen","applepen","pine","pineapple"] Output: ["pine apple pen apple","pineapple pen apple","pine applepen apple"] Explanation: Note that you are allowed to reuse a dictionary word.
Example 3:
Input: s = "catsandog", wordDict = ["cats","dog","sand","and","cat"] Output: []
Constraints:
1 <= s.length <= 201 <= wordDict.length <= 10001 <= wordDict[i].length <= 10s and wordDict[i] consist of only lowercase English letters.wordDict are unique.Problem Overview: Given a string s and a dictionary of valid words, return all possible sentences formed by inserting spaces in s so every segment exists in the dictionary. Unlike Word Break I, this problem requires generating every valid sentence rather than just checking feasibility.
Approach 1: Backtracking with Memoization (Time: O(n * 2^n), Space: O(n * 2^n))
This approach explores every possible prefix of the string and recursively builds sentences from the remaining suffix. For each index, iterate through the string and check whether s[i:j] exists in a hash set built from the dictionary. If it does, recursively solve the suffix starting at j. Memoization stores results for previously computed indices so the same substring is never recomputed. Without memoization the recursion tree explodes; caching reduces repeated work significantly. The recursion essentially builds a tree of sentence combinations where each node represents a valid dictionary split. This technique heavily uses backtracking and memoization to efficiently enumerate all possibilities.
Approach 2: Dynamic Programming with Sentence Reconstruction (Time: O(n^2 + n * 2^n), Space: O(n * 2^n))
Dynamic programming first determines which prefixes of the string can form valid segmentations. Create a DP array where dp[i] stores all sentences that can construct the substring s[0:i]. Iterate through indices and check each previous position j. If s[j:i] is a dictionary word and dp[j] already contains valid sentences, append the new word to those sentences. This gradually builds complete results for dp[n]. The dictionary lookup runs in constant time using a hash set, making substring validation efficient. This technique leverages dynamic programming on top of standard string manipulation.
Approach 3: Trie Optimized Search (Time: O(n * 2^n), Space: O(n * 2^n + dict))
Instead of repeatedly checking substrings against a hash set, you can store the dictionary in a Trie. Starting from index i, walk the Trie while scanning characters in the string. Each time you hit a terminal node, you found a valid word and recursively process the remainder. Trie traversal avoids repeated substring allocations and speeds up dictionary checks when the word list is large. This approach pairs naturally with recursion and memoization while reducing lookup overhead using a Trie.
Recommended for interviews: Backtracking with memoization is the most common solution expected by interviewers. It clearly demonstrates recursive decomposition and caching to control exponential branching. Dynamic programming is also strong if you prefer bottom‑up reasoning. A naive brute force recursion without memoization proves the idea but performs poorly on longer inputs, so the optimized memoized version usually signals stronger problem‑solving ability.
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Backtracking with Memoization | O(n * 2^n) | O(n * 2^n) | Most common interview solution when generating all sentence combinations |
| Dynamic Programming | O(n^2 + n * 2^n) | O(n * 2^n) | When you prefer bottom-up reasoning and incremental sentence building |
| Trie + DFS | O(n * 2^n) | O(n * 2^n + dict) | Large dictionaries where faster prefix lookup improves performance |