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. A sequence of words forms a valid word square if the kth row and kth column read the exact same string for each 0 <= k < max(numRows, numColumns).
Try all possible word combinations recursively. At each step, check if the current partial square is valid. Very slow as it doesn't use the prefix property effectively.
⏱ O(N^L) where N is words, L is length.💾 O(L)
java
classSolution{publicList<List<String>>wordSquares(String[] words){List<List<String>> res =newArrayList<>();if(words ==null|| words.length ==0)return res;int n = words[0].length();for(String w : words){List<String> list =newArrayList<>(); list.add(w);backtrack(res, list, words, n);}return res;}privatevoidbacktrack(List<List<String>> res,List<String> list,String[] words,int n){if(list.size()== n){ res.add(newArrayList<>(list));return;}int idx = list.size();StringBuilder sb =newStringBuilder();for(String s : list) sb.append(s.charAt(idx));String prefix = sb.toString();for(String word : words){if(word.startsWith(prefix)){ list.add(word);backtrack(res, list, words, n); list.remove(list.size()-1);}}}}
Approach 2
Level III: Trie + Backtracking
Intuition
At each step k, we need to find words that start with a specific prefix. This prefix is formed by the characters at position k of the words already chosen. A Trie is the perfect data structure to quickly fetch all words sharing a common prefix.
⏱ O(N * 26^L)💾 O(Total Chars)
java
importjava.util.*;classSolution{classNode{Node[] children =newNode[26];List<String> wordList =newArrayList<>();}publicList<List<String>>wordSquares(String[] words){Node root =newNode();for(String w : words){Node curr = root;for(char c : w.toCharArray()){int i = c -'a';if(curr.children[i]==null) curr.children[i]=newNode(); curr = curr.children[i]; curr.wordList.add(w);}}List<List<String>> res =newArrayList<>();int n = words[0].length();for(String w : words){List<String> square =newArrayList<>(); square.add(w);backtracking(1, n, square, root, res);}return res;}privatevoidbacktracking(int step,int n,List<String> square,Node root,List<List<String>> res){if(step == n){ res.add(newArrayList<>(square));return;}StringBuilder prefix =newStringBuilder();for(String s : square) prefix.append(s.charAt(step));Node curr = root;for(char c : prefix.toString().toCharArray()){if(curr.children[c-'a']==null)return; curr = curr.children[c-'a'];}for(String candidate : curr.wordList){ square.add(candidate);backtracking(step +1, n, square, root, res); square.remove(square.size()-1);}}}