Watch 10 video solutions for Word Squares, a hard level problem involving Array, String, Backtracking. This walkthrough by Sonu Raj has 5,459 views views. Want to try solving it yourself? Practice on FleetCode or read the detailed text solution.
Given an array of unique strings words, return all the word squares you can build from words. The same word from words can be used multiple times. You can return the answer in any order.
A sequence of strings forms a valid word square if the kth row and column read the same string, where 0 <= k < max(numRows, numColumns).
["ball","area","lead","lady"] forms a word square because each word reads the same both horizontally and vertically.
Example 1:
Input: words = ["area","lead","wall","lady","ball"] Output: [["ball","area","lead","lady"],["wall","area","lead","lady"]] Explanation: The output consists of two word squares. The order of output does not matter (just the order of words in each word square matters).
Example 2:
Input: words = ["abat","baba","atan","atal"] Output: [["baba","abat","baba","atal"],["baba","abat","baba","atan"]] Explanation: The output consists of two word squares. The order of output does not matter (just the order of words in each word square matters).
Constraints:
1 <= words.length <= 10001 <= words[i].length <= 4words[i] have the same length.words[i] consists of only lowercase English letters.words[i] are unique.Problem Overview: Given a list of words with the same length, build all possible word squares. A word square means the k-th row and k-th column form the same string. If the first row starts with "ball", the first column must also read "ball". The task is to generate every valid arrangement of words that satisfies this constraint.
Approach 1: Backtracking with Prefix Scanning (Brute Force) (Time: O(N^L * L), Space: O(L))
Start with each word as the first row of the square and build the rest using backtracking. At step k, derive the required prefix for the next word using the characters from column k of previously placed rows. Scan the entire word list and pick candidates whose prefix matches. Continue recursively until the square reaches size L. This approach works but repeatedly scanning the array makes prefix lookups expensive.
Approach 2: Trie + Backtracking (Optimized) (Time: O(N * L^2) average, Space: O(N * L))
Speed up candidate lookup by indexing all words in a Trie. Each node stores the list of word indices that share the prefix represented by that node. During backtracking, compute the prefix needed for the next row and query the Trie to instantly retrieve all valid candidates. This removes the repeated full-array scans and turns prefix lookup into O(L). The recursive search builds squares row by row while maintaining the row/column symmetry constraint.
The key observation: when you already placed k rows, the next word must start with the characters formed by column k. Using a Trie makes this prefix query efficient. The remaining logic is standard depth‑first exploration over candidate words.
This problem heavily combines array traversal, string prefix construction, and structured pruning using a Trie.
Recommended for interviews: Trie + backtracking is the expected solution. Brute force backtracking demonstrates understanding of the square constraint, but efficient prefix lookup using a Trie shows stronger algorithmic design and pruning strategy.
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Backtracking with Prefix Scanning | O(N^L * L) | O(L) | Small input sizes or when demonstrating the base backtracking idea |
| Trie + Backtracking | O(N * L^2) average | O(N * L) | Optimal approach for interviews and large word lists with many prefix queries |