Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/build/
/.gradle/
.build.gradle
.build.gradle
/.idea/
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package algorithms.curated170.hard;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class WordSquaresTrieBacktracking {
public static class Solution {
public final static int LETTER_a = 97;

public List<List<String>> wordSquares(String[] words) {
TrieNode root = buiildTrie(words);
int n = words[0].length();
TrieNode[] trieNodeState = new TrieNode[n];
Arrays.fill(trieNodeState, root);
List<List<String>> ans = new ArrayList<>();
dfs(0, new char[n][n], ans, trieNodeState);
return ans;
}
void dfs(int rowIndex, char[][] matrix, List<List<String>> ans, TrieNode[] trieNodeState) {
if (rowIndex == matrix.length) {
ans.add(convertMatrixToList(matrix, rowIndex));
return;
}
TrieNode[] trieNodeStateNext = new TrieNode[trieNodeState.length];
for (String candidate : trieNodeState[rowIndex].list) {

if (isSymmetric(matrix, candidate, rowIndex, trieNodeState, trieNodeStateNext)){
Copy link
Collaborator

@ErdemT09 ErdemT09 Jul 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: isSymmetric() method handles the backtracking part too. As we call the method, it overrides the character matrix with the candidate string. If it's okay, we continue with it. If it's not symmetric, we don't. Either way, it get's overriden in the next function call.

dfs(rowIndex + 1, matrix, ans, trieNodeStateNext);
}
}
}

private boolean isSymmetric(char[][] matrix, String candidate, int rowIndex,
TrieNode[] trieNodeState, TrieNode[] trieNodeStateNext) {

int i = rowIndex;
while (i < matrix.length) {
char ch = candidate.charAt(i);
matrix[rowIndex][i] = ch;
if (i > rowIndex) {
matrix[i][rowIndex] = ch;
int letterIndex = letterIndex(ch);
if (trieNodeState[i].children[letterIndex] == null) break;
trieNodeStateNext[i] = trieNodeState[i].children[letterIndex];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that trieNodeStateNext doesn't do anything. If I'm not mistaken, we can remove it.

Copy link
Collaborator Author

@altay9 altay9 Jul 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It has a function as a kind of "backtracking" to the older "trieNodeState" keeping the older state immutable.
But, we can try removing of course.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't see it being inputted into dfs. It makes more sense now, as we are traversing after some prefix already gone through.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This allows duplicate usage of words, as the problem allows.

}
i++;
}
return (i == matrix.length);
}

TrieNode buiildTrie(String[] words){
TrieNode root = new TrieNode();
for (String w : words) {
root.list.add(w);
TrieNode tn = root;
for (char ch : w.toCharArray()) {
int index = letterIndex(ch);
if (tn.children[index] == null){
tn.children[index] = new TrieNode();
}
tn = tn.children[index];
tn.list.add(w);
}
}
return root;
}
private List<String> convertMatrixToList(char[][] matrix, int rowIndex) {
List<String> words = new ArrayList<>(rowIndex);
for (char[] ca : matrix) words.add(new String(ca));
return words;
}


private int letterIndex(char ch)
{
return (ch - LETTER_a);
}

class TrieNode {
List<String> list;
TrieNode[] children;
TrieNode() {
list = new ArrayList<>();
children = new TrieNode[26];
}
}
}
public static void main(String[] args) {
Solution solution = new Solution();
solution.wordSquares(new String[]{ "area","lead","wall","lady","ball"});
}
}