Given an array arr[] of n unique numeric strings, all of the same length, find all possible arrangements of these strings that form a number square. Strings from the list can be reused any number of times within a square. A number square is a special grid, where every row reads the same as the corresponding column. Return all valid arrangements in any order, but the order of strings within each arrangement matters.
Examples:
Input: arr[] = ["221", "211", "212", "121"] Output: [["121", "212", "121"], ["212", "121", "211"], ["212", "121", "212"], ["221", "212", "121"]] Explanation: There are 4 valid arrangements. For example in ["221", "212", "121"] -> row 0 = "221", col 0 = "221", row 1 = "212", col 1 = "212", row 2 = "121", col 2 = "121".
[Naive Approach] Generate All Possible Arrangements and Validate - O(n ^ L * L ^ 2) Time and O(L) Space
The idea is to generate every possible arrangement of L strings using recursion. For each completed arrangement, check whether every row matches its corresponding column. If it does, store the arrangement as a valid number square.
Working of Approach:
Generate all possible arrangements of L rows by choosing any string from arr for each row using recursion.
After forming a complete square, check whether every row is equal to its corresponding column.
If the condition is satisfied, store the arrangement in the result list.
Finally, return all valid number square arrangements.
C++
#include<iostream>#include<vector>#include<string>usingnamespacestd;vector<vector<string>>res;intlen;// Check whether current arrangement is a valid number square.boolisValid(vector<string>&curr){for(inti=0;i<len;i++){for(intj=0;j<len;j++){if(curr[i][j]!=curr[j][i])returnfalse;}}returntrue;}// Generate all possible arrangements.voidsolve(vector<string>&arr,vector<string>&curr,introw){if(row==len){if(isValid(curr))res.push_back(curr);return;}// Try every string for the current row.for(string&s:arr){curr.push_back(s);solve(arr,curr,row+1);curr.pop_back();}}vector<vector<string>>numberSquares(vector<string>&arr){len=arr[0].size();vector<string>curr;solve(arr,curr,0);returnres;}intmain(){vector<string>arr={"1111","1222"};vector<vector<string>>res=numberSquares(arr);cout<<"[";for(inti=0;i<res.size();i++){cout<<"[";for(intj=0;j<res[i].size();j++){cout<<"\""<<res[i][j]<<"\"";if(j!=res[i].size()-1)cout<<", ";}cout<<"]";if(i!=res.size()-1)cout<<", ";}cout<<"]";return0;}
Java
importjava.util.*;classGFG{staticArrayList<ArrayList<String>>res=newArrayList<>();staticintlen;// Check whether current arrangement is a valid number square.staticbooleanisValid(ArrayList<String>curr){for(inti=0;i<len;i++){for(intj=0;j<len;j++){if(curr.get(i).charAt(j)!=curr.get(j).charAt(i))returnfalse;}}returntrue;}// Generate all possible arrangements.staticvoidsolve(String[]arr,ArrayList<String>curr,introw){if(row==len){if(isValid(curr))res.add(newArrayList<>(curr));return;}// Try every string for the current row.for(Strings:arr){curr.add(s);solve(arr,curr,row+1);curr.remove(curr.size()-1);}}publicstaticArrayList<ArrayList<String>>numberSquares(String[]arr){res.clear();len=arr[0].length();ArrayList<String>curr=newArrayList<>();solve(arr,curr,0);returnres;}publicstaticvoidmain(String[]args){String[]arr={"1111","1222"};ArrayList<ArrayList<String>>res=numberSquares(arr);System.out.print("[");for(inti=0;i<res.size();i++){System.out.print("[");for(intj=0;j<res.get(i).size();j++){System.out.print("\""+res.get(i).get(j)+"\"");if(j!=res.get(i).size()-1)System.out.print(", ");}System.out.print("]");if(i!=res.size()-1)System.out.print(", ");}System.out.print("]");}}
Python
# Python Program to generate all possible arrangements# and validate each arrangement as a number square.res=[]length=0# Check whether current arrangement is a valid number square.defisValid(curr):foriinrange(length):forjinrange(length):ifcurr[i][j]!=curr[j][i]:returnFalsereturnTrue# Generate all possible arrangements.defsolve(arr,curr,row):ifrow==length:ifisValid(curr):res.append(curr.copy())return# Try every string for the current row.forsinarr:curr.append(s)solve(arr,curr,row+1)curr.pop()defnumberSquares(arr):globallength,resres=[]length=len(arr[0])curr=[]solve(arr,curr,0)returnresif__name__=="__main__":arr=["1111","1222"]res=numberSquares(arr)print("[",end="")foriinrange(len(res)):print("[",end="")forjinrange(len(res[i])):print("\""+res[i][j]+"\"",end="")ifj!=len(res[i])-1:print(", ",end="")print("]",end="")ifi!=len(res)-1:print(", ",end="")print("]")
C#
usingSystem;usingSystem.Collections.Generic;classGFG{staticList<List<string>>res=newList<List<string>>();staticintlen;// Check whether current arrangement is a valid number// square.staticboolisValid(List<string>curr){for(inti=0;i<len;i++){for(intj=0;j<len;j++){if(curr[i][j]!=curr[j][i])returnfalse;}}returntrue;}// Generate all possible arrangements.staticvoidsolve(string[]arr,List<string>curr,introw){if(row==len){if(isValid(curr))res.Add(newList<string>(curr));return;}// Try every string for the current row.foreach(stringsinarr){curr.Add(s);solve(arr,curr,row+1);curr.RemoveAt(curr.Count-1);}}publicList<List<string>>numberSquares(string[]arr){res.Clear();len=arr[0].Length;List<string>curr=newList<string>();solve(arr,curr,0);returnres;}publicstaticvoidMain(){string[]arr={"1111","1222"};GFGobj=newGFG();List<List<string>>res=obj.numberSquares(arr);Console.Write("[");for(inti=0;i<res.Count;i++){Console.Write("[");for(intj=0;j<res[i].Count;j++){Console.Write("\""+res[i][j]+"\"");if(j!=res[i].Count-1)Console.Write(", ");}Console.Write("]");if(i!=res.Count-1)Console.Write(", ");}Console.Write("]");}}
JavaScript
letres=[];letlen=0;// Check whether current arrangement is a valid number// square.functionisValid(curr){for(leti=0;i<len;i++){for(letj=0;j<len;j++){if(curr[i][j]!==curr[j][i])returnfalse;}}returntrue;}// Generate all possible arrangements.functionsolve(arr,curr,row){if(row===len){if(isValid(curr))res.push([...curr]);return;}// Try every string for the current row.for(letsofarr){curr.push(s);solve(arr,curr,row+1);curr.pop();}}functionnumberSquares(arr){len=arr[0].length;res=[];letcurr=[];solve(arr,curr,0);returnres;}// Driver Codeletarr=["1111","1222"];letresult=numberSquares(arr);console.log(JSON.stringify(result));
Time Complexity: O(n ^ L × L ^ 2) - Generates all possible arrangements and validates each square by comparing rows and columns. Space Complexity: O(L) - Stores the current arrangement during recursion.
[Better Approach] Using Hash Map with Backtracking - O(n * L + Ans × L ^ 2) Time and O(n * L) Space
The idea is to store all prefixes of every string in a hash map. While building the square row by row, construct the required prefix for the next row and retrieve only the strings having that prefix. This prunes invalid choices early and generates only valid number squares.
Working of Approach:
Store every prefix of each string in a hash map, where each prefix maps to possible strings having that prefix.
During backtracking, build the required prefix for the next row using the already selected rows.
Retrieve only matching strings from the hash map and recursively build the remaining rows.
When L rows are selected, add the valid number square to the result.
C++
#include<iostream>#include<vector>#include<string>#include<unordered_map>usingnamespacestd;unordered_map<string,vector<string>>mp;vector<vector<string>>res;intlen;// Generate all possible number squares.voidbacktrack(vector<string>&curr,introw){// A valid number square is formed.if(row==len){res.push_back(curr);return;}// Build the required prefix for the current row.stringprefix="";for(inti=0;i<row;i++)prefix+=curr[i][row];// Try all strings having the required prefix.for(string&s:mp[prefix]){curr.push_back(s);backtrack(curr,row+1);curr.pop_back();}}vector<vector<string>>numberSquares(vector<string>&arr){len=arr[0].size();// Store every prefix of every string.for(string&s:arr){for(inti=0;i<=len;i++)mp[s.substr(0,i)].push_back(s);}vector<string>curr;// Try every string as the first row.for(string&s:arr){curr.push_back(s);backtrack(curr,1);curr.pop_back();}returnres;}intmain(){vector<string>arr={"1111","1222"};vector<vector<string>>res=numberSquares(arr);cout<<"[";for(inti=0;i<res.size();i++){cout<<"[";for(intj=0;j<res[i].size();j++){cout<<"\""<<res[i][j]<<"\"";if(j!=res[i].size()-1)cout<<", ";}cout<<"]";if(i!=res.size()-1)cout<<", ";}cout<<"]";return0;}
Java
importjava.util.*;classGFG{staticHashMap<String,ArrayList<String>>mp=newHashMap<>();staticArrayList<ArrayList<String>>res=newArrayList<>();staticintlen;// Generate all possible number squares.staticvoidbacktrack(ArrayList<String>curr,introw){// A valid number square is formed.if(row==len){res.add(newArrayList<>(curr));return;}// Build the required prefix for the current row.Stringprefix="";for(inti=0;i<row;i++)prefix+=curr.get(i).charAt(row);// Try all strings having the required prefix.for(Strings:mp.getOrDefault(prefix,newArrayList<>())){curr.add(s);backtrack(curr,row+1);curr.remove(curr.size()-1);}}staticArrayList<ArrayList<String>>numberSquares(String[]arr){mp.clear();res.clear();len=arr[0].length();// Store every prefix of every string.for(Strings:arr){for(inti=0;i<=len;i++){Stringprefix=s.substring(0,i);mp.putIfAbsent(prefix,newArrayList<>());mp.get(prefix).add(s);}}ArrayList<String>curr=newArrayList<>();// Try every string as the first row.for(Strings:arr){curr.add(s);backtrack(curr,1);curr.remove(curr.size()-1);}returnres;}// Driver Codepublicstaticvoidmain(String[]args){String[]arr={"1111","1222"};ArrayList<ArrayList<String>>result=numberSquares(arr);System.out.print("[");for(inti=0;i<result.size();i++){System.out.print("[");for(intj=0;j<result.get(i).size();j++){System.out.print("\""+result.get(i).get(j)+"\"");if(j!=result.get(i).size()-1)System.out.print(", ");}System.out.print("]");if(i!=result.size()-1)System.out.print(", ");}System.out.print("]");}}
Python
# Python Program to generate number squares# using Hash Map and Backtracking.mp={}res=[]length=0# Generate all possible number squares.defbacktrack(curr,row):globallength# A valid number square is formed.ifrow==length:res.append(curr.copy())return# Build the required prefix for the current row.prefix=""foriinrange(row):prefix+=curr[i][row]# Try all strings having the required prefix.forsinmp.get(prefix,[]):curr.append(s)backtrack(curr,row+1)curr.pop()defnumberSquares(arr):globallength,mp,resmp={}res=[]length=len(arr[0])# Store every prefix of every string.forsinarr:foriinrange(length+1):prefix=s[:i]ifprefixnotinmp:mp[prefix]=[]mp[prefix].append(s)curr=[]# Try every string as the first row.forsinarr:curr.append(s)backtrack(curr,1)curr.pop()returnresif__name__=="__main__":arr=["1111","1222"]result=numberSquares(arr)print("[",end="")foriinrange(len(result)):print("[",end="")forjinrange(len(result[i])):print("\""+result[i][j]+"\"",end="")ifj!=len(result[i])-1:print(", ",end="")print("]",end="")ifi!=len(result)-1:print(", ",end="")print("]")
C#
usingSystem;usingSystem.Collections.Generic;classGFG{staticDictionary<string,List<string>>mp=newDictionary<string,List<string>>();staticList<List<string>>res=newList<List<string>>();staticintlen;// Generate all possible number squares.staticvoidbacktrack(List<string>curr,introw){// A valid number square is formed.if(row==len){res.Add(newList<string>(curr));return;}// Build the required prefix for the current row.stringprefix="";for(inti=0;i<row;i++)prefix+=curr[i][row];// Try all strings having the required prefix.if(mp.ContainsKey(prefix)){foreach(stringsinmp[prefix]){curr.Add(s);backtrack(curr,row+1);curr.RemoveAt(curr.Count-1);}}}staticList<List<string>>numberSquares(string[]arr){mp.Clear();res.Clear();len=arr[0].Length;// Store every prefix of every string.foreach(stringsinarr){for(inti=0;i<=len;i++){stringprefix=s.Substring(0,i);if(!mp.ContainsKey(prefix))mp[prefix]=newList<string>();mp[prefix].Add(s);}}List<string>curr=newList<string>();// Try every string as the first row.foreach(stringsinarr){curr.Add(s);backtrack(curr,1);curr.RemoveAt(curr.Count-1);}returnres;}// Driver CodepublicstaticvoidMain(){string[]arr={"1111","1222"};List<List<string>>result=numberSquares(arr);Console.Write("[");for(inti=0;i<result.Count;i++){Console.Write("[");for(intj=0;j<result[i].Count;j++){Console.Write("\""+result[i][j]+"\"");if(j!=result[i].Count-1)Console.Write(", ");}Console.Write("]");if(i!=result.Count-1)Console.Write(", ");}Console.Write("]");}}
JavaScript
// JavaScript Program to generate number squares// using Hash Map and Backtracking.letmp=newMap();letres=[];letlen=0;// Generate all possible number squares.functionbacktrack(curr,row){// A valid number square is formed.if(row==len){res.push([...curr]);return;}// Build the required prefix for the current row.letprefix="";for(leti=0;i<row;i++)prefix+=curr[i][row];// Try all strings having the required prefix.if(mp.has(prefix)){for(letsofmp.get(prefix)){curr.push(s);backtrack(curr,row+1);curr.pop();}}}functionnumberSquares(arr){mp=newMap();res=[];len=arr[0].length;// Store every prefix of every string.for(letsofarr){for(leti=0;i<=len;i++){letprefix=s.substring(0,i);if(!mp.has(prefix))mp.set(prefix,[]);mp.get(prefix).push(s);}}letcurr=[];// Try every string as the first row.for(letsofarr){curr.push(s);backtrack(curr,1);curr.pop();}returnres;}// Driver Codeletarr=["1111","1222"];letresult=numberSquares(arr);console.log(JSON.stringify(result));
Time Complexity: O(n × L + Ans × L ^ 2) - Stores all prefixes and explores only strings matching the required prefix while forming valid squares. Space Complexity: O(n × L) - Stores prefixes of all strings in the hash map.
[Expected Approach] Using Trie with Backtracking - O(n * L + Ans * L ^ 2) Time and O(n * L) Space
The idea is to insert all strings into a Trie, where every node stores the strings sharing its prefix. During backtracking, build the required prefix for the next row and use the Trie to directly retrieve only the matching strings. This efficiently prunes invalid choices while generating all valid number squares.
Working of Approach:
First, insert all strings into the Trie and store each string at every Trie node along its prefix path.
Start backtracking by selecting each string as the first row of the number square.
For the next row, build the required prefix using characters from the already selected rows and search matching strings in the Trie.
Recursively add valid strings having the required prefix until the square size is reached.
When all rows are selected, store the formed arrangement as a valid number square.
Let us understand with an example: Input: arr[] = ["1111", "1222"]
Insert all strings into the Trie. For each prefix, store the strings having that prefix.
Choose "1111" as the first row. Required prefix for the next row is "1", so Trie returns {"1111", "1222"}.
Choose "1111" again repeatedly to form ["1111","1111","1111","1111"], which satisfies row-column conditions and is stored.
Backtracking tries "1222" for the next rows, forming ["1111","1222","1222","1222"], which is also a valid number square.
All possible valid arrangements are generated and returned as the final result.
#include<iostream>#include<vector>#include<string>#include<algorithm>usingnamespacestd;structTrieNode{TrieNode*children[10];vector<string>words;TrieNode(){fill(children,children+10,nullptr);}};TrieNode*root;voidinsert(string&word){TrieNode*node=root;for(charch:word){intidx=ch-'0';if(!node->children[idx])node->children[idx]=newTrieNode();node=node->children[idx];// Store string at every node along its pathnode->words.push_back(word);}}vector<string>getStringsWithPrefix(string&prefix){TrieNode*node=root;for(charch:prefix){intidx=ch-'0';if(!node->children[idx])return{};node=node->children[idx];}returnnode->words;}voidbacktrack(vector<string>&sq,intlen,vector<vector<string>>&res){if(sq.size()==len){res.push_back(sq);return;}intidx=sq.size();// Build required prefix for next stringstringprefix="";for(inti=0;i<idx;i++)prefix+=sq[i][idx];for(string&s:getStringsWithPrefix(prefix)){sq.push_back(s);backtrack(sq,len,res);sq.pop_back();}}vector<vector<string>>numberSquares(vector<string>&arr){root=newTrieNode();intlen=arr[0].size();// Build trie with all stringsfor(string&s:arr)insert(s);vector<vector<string>>res;vector<string>sq;for(string&s:arr){sq.push_back(s);backtrack(sq,len,res);sq.pop_back();}returnres;}intmain(){vector<string>arr={"1111","1222"};vector<vector<string>>res=numberSquares(arr);cout<<"[";for(inti=0;i<res.size();i++){cout<<"[";for(intj=0;j<res[i].size();j++){cout<<"\""<<res[i][j]<<"\"";if(j!=res[i].size()-1)cout<<", ";}cout<<"]";if(i!=res.size()-1)cout<<", ";}cout<<"]";return0;}
Java
importjava.util.*;classGFG{staticclassTrieNode{TrieNode[]children=newTrieNode[10];ArrayList<String>words=newArrayList<>();}staticTrieNoderoot;staticvoidinsert(Stringword){TrieNodenode=root;for(charch:word.toCharArray()){intidx=ch-'0';if(node.children[idx]==null)node.children[idx]=newTrieNode();node=node.children[idx];// Store string at every node along its pathnode.words.add(word);}}staticArrayList<String>getStringsWithPrefix(Stringprefix){TrieNodenode=root;for(charch:prefix.toCharArray()){intidx=ch-'0';if(node.children[idx]==null)returnnewArrayList<>();node=node.children[idx];}returnnode.words;}staticvoidbacktrack(ArrayList<String>sq,intlen,ArrayList<ArrayList<String>>res){if(sq.size()==len){res.add(newArrayList<>(sq));return;}intidx=sq.size();// Build required prefix for next stringStringprefix="";for(inti=0;i<idx;i++)prefix+=sq.get(i).charAt(idx);for(Strings:getStringsWithPrefix(prefix)){sq.add(s);backtrack(sq,len,res);sq.remove(sq.size()-1);}}staticArrayList<ArrayList<String>>numberSquares(String[]arr){root=newTrieNode();intlen=arr[0].length();// Build trie with all stringsfor(Strings:arr)insert(s);ArrayList<ArrayList<String>>res=newArrayList<>();ArrayList<String>sq=newArrayList<>();for(Strings:arr){sq.add(s);backtrack(sq,len,res);sq.remove(sq.size()-1);}returnres;}// Driver Codepublicstaticvoidmain(String[]args){String[]arr={"1111","1222"};ArrayList<ArrayList<String>>res=numberSquares(arr);System.out.print("[");for(inti=0;i<res.size();i++){System.out.print("[");for(intj=0;j<res.get(i).size();j++){System.out.print("\""+res.get(i).get(j)+"\"");if(j!=res.get(i).size()-1)System.out.print(", ");}System.out.print("]");if(i!=res.size()-1)System.out.print(", ");}System.out.print("]");}}
Python
# Python Program to generate number squares# using Trie and Backtracking.classTrieNode:def__init__(self):self.children=[None]*10self.words=[]root=Nonedefinsert(word):node=rootforchinword:idx=ord(ch)-ord('0')ifnode.children[idx]isNone:node.children[idx]=TrieNode()node=node.children[idx]# Store string at every node along its pathnode.words.append(word)defgetStringsWithPrefix(prefix):node=rootforchinprefix:idx=ord(ch)-ord('0')ifnode.children[idx]isNone:return[]node=node.children[idx]returnnode.wordsdefbacktrack(sq,length,res):iflen(sq)==length:res.append(sq.copy())returnidx=len(sq)# Build required prefix for next stringprefix=""foriinrange(idx):prefix+=sq[i][idx]forsingetStringsWithPrefix(prefix):sq.append(s)backtrack(sq,length,res)sq.pop()defnumberSquares(arr):globalrootroot=TrieNode()length=len(arr[0])# Build trie with all stringsforsinarr:insert(s)res=[]sq=[]forsinarr:sq.append(s)backtrack(sq,length,res)sq.pop()returnresif__name__=="__main__":arr=["1111","1222"]result=numberSquares(arr)print(result)
C#
usingSystem;usingSystem.Collections.Generic;classGFG{classTrieNode{publicTrieNode[]children=newTrieNode[10];publicList<string>words=newList<string>();}TrieNoderoot;voidinsert(stringword){TrieNodenode=root;foreach(charchinword){intidx=ch-'0';if(node.children[idx]==null)node.children[idx]=newTrieNode();node=node.children[idx];// Store string at every node along its pathnode.words.Add(word);}}List<string>getStringsWithPrefix(stringprefix){TrieNodenode=root;foreach(charchinprefix){intidx=ch-'0';if(node.children[idx]==null)returnnewList<string>();node=node.children[idx];}returnnode.words;}voidbacktrack(List<string>sq,intlen,List<List<string>>res){if(sq.Count==len){res.Add(newList<string>(sq));return;}intidx=sq.Count;// Build required prefix for next stringstringprefix="";for(inti=0;i<idx;i++)prefix+=sq[i][idx];foreach(stringsingetStringsWithPrefix(prefix)){sq.Add(s);backtrack(sq,len,res);sq.RemoveAt(sq.Count-1);}}publicList<List<string>>numberSquares(string[]arr){root=newTrieNode();intlen=arr[0].Length;// Build trie with all stringsforeach(stringsinarr)insert(s);List<List<string>>res=newList<List<string>>();List<string>sq=newList<string>();foreach(stringsinarr){sq.Add(s);backtrack(sq,len,res);sq.RemoveAt(sq.Count-1);}returnres;}// Driver CodepublicstaticvoidMain(){GFGobj=newGFG();string[]arr={"1111","1222"};List<List<string>>res=obj.numberSquares(arr);Console.Write("[");for(inti=0;i<res.Count;i++){Console.Write("[");for(intj=0;j<res[i].Count;j++){Console.Write("\""+res[i][j]+"\"");if(j!=res[i].Count-1)Console.Write(", ");}Console.Write("]");if(i!=res.Count-1)Console.Write(", ");}Console.Write("]");}}
JavaScript
classTrieNode{constructor(){this.children=Array(10).fill(null);this.words=[];}}letroot=null;functioninsert(word){letnode=root;for(letchofword){letidx=ch.charCodeAt(0)-"0".charCodeAt(0);if(!node.children[idx]){node.children[idx]=newTrieNode();}node=node.children[idx];// Store string at every node along its pathnode.words.push(word);}}functiongetStringsWithPrefix(prefix){letnode=root;for(letchofprefix){letidx=ch.charCodeAt(0)-"0".charCodeAt(0);if(!node.children[idx]){return[];}node=node.children[idx];}returnnode.words;}functionbacktrack(sq,len,res){if(sq.length===len){res.push([...sq]);return;}letidx=sq.length;// Build required prefix for next stringletprefix="";for(leti=0;i<idx;i++){prefix+=sq[i][idx];}for(letsofgetStringsWithPrefix(prefix)){sq.push(s);backtrack(sq,len,res);sq.pop();}}functionnumberSquares(arr){root=newTrieNode();letlen=arr[0].length;// Build trie with all stringsfor(letsofarr){insert(s);}letres=[];letsq=[];for(letsofarr){sq.push(s);backtrack(sq,len,res);sq.pop();}returnres;}// Driver Codeletarr=["1111","1222"];letresult=numberSquares(arr);console.log(JSON.stringify(result));
Time Complexity: O(n × L + Ans × L ^ 2) - Builds the Trie and generates only valid arrangements by searching required prefixes efficiently. Space Complexity: O(n × L) - Stores all strings and their prefixes inside the Trie.