classTrieNode{
HashMap<Character, TrieNode> children =newHashMap<Character, TrieNode>();
String word = null;publicTrieNode(){}}classSolution{char[][] _board = null;
ArrayList<String> _result =newArrayList<String>();public List<String>findWords(char[][] board, String[] words){// Step 1). Construct the Trie
TrieNode root =newTrieNode();for(String word : words){
TrieNode node = root;for(Character letter : word.toCharArray()){if(node.children.containsKey(letter)){
node = node.children.get(letter);}else{
TrieNode newNode =newTrieNode();
node.children.put(letter, newNode);
node = newNode;}}
node.word = word;// store words in Trie}this._board = board;// Step 2). Backtracking starting for each cell in the boardfor(int row =0; row < board.length;++row){for(int col =0; col < board[row].length;++col){if(root.children.containsKey(board[row][col])){backtracking(row, col, root);}}}returnthis._result;}privatevoidbacktracking(int row,int col, TrieNode parent){
Character letter =this._board[row][col];
TrieNode currNode = parent.children.get(letter);// check if there is any matchif(currNode.word != null){this._result.add(currNode.word);
currNode.word = null;}// mark the current letter before the EXPLORATIONthis._board[row][col]='#';// explore neighbor cells in around-clock directions: up, right, down, leftint[] rowOffset ={-1,0,1,0};int[] colOffset ={0,1,0,-1};for(int i =0; i <4;++i){int newRow = row + rowOffset[i];int newCol = col + colOffset[i];if(newRow <0|| newRow >=this._board.length || newCol <0|| newCol >=this._board[0].length){continue;}if(currNode.children.containsKey(this._board[newRow][newCol])){backtracking(newRow, newCol, currNode);}}// End of EXPLORATION, restore the original letter in the board.this._board[row][col]= letter;// Optimization: incrementally remove the leaf nodesif(currNode.children.isEmpty()){
parent.children.remove(letter);}}}