212. Word search II
Given a two-dimensional grid board and a list of words in a dictionary, find out all the words that appear in the two-dimensional grid and dictionary at the same time.
Words must be formed alphabetically by letters in adjacent cells, where "adjacent" cells are those adjacent horizontally or vertically. Letters in the same cell are not allowed to be reused in a word.
Example:
Input:
words = ["oath","pea","eat","rain"] and board = [ ['o','a','a','n'], ['e','t','a','e'], ['i','h','k','r'], ['i','f','l','v'] ]
Output: ["eat", "oat"]
Explain:
You can assume that all input consists of lowercase letters a-z.
Tips:
You need to optimize the backtracking algorithm to pass a larger amount of data. Can you stop looking back earlier?
If the current word does not exist in the prefixes of all words, you can immediately stop backtracking. What kind of data structure can effectively perform such operations? Is the hash feasible? Why? How about the prefix tree? If you want to learn how to implement a basic prefix tree, first look at this problem: implement Trie (prefix tree).
PS:
First, build a dictionary tree, and then add a dictionary tree in dfs. Those starting with a certain string can reduce the number of searches
class TrieNode { private static final int ALPHABET_SIZE = 26; TrieNode[] children = new TrieNode[ALPHABET_SIZE]; // Determine whether this prefix is the end of a string boolean isEndOfWord = false; TrieNode() { isEndOfWord = false; for (int i = 0; i < ALPHABET_SIZE; i++) children[i] = null; } } class Trie { public TrieNode root; /** Initialize your data structure here. */ public Trie() { root = new TrieNode(); } /** Inserts a word into the trie. */ public void insert(String word) { TrieNode curNode = root; int index; for (int i = 0; i < word.length(); i++) { index = word.charAt(i) - 'a'; if (curNode.children[index] == null) { curNode.children[index] = new TrieNode(); } curNode = curNode.children[index]; } curNode.isEndOfWord = true; } } class Solution { public List<String> findWords(char[][] board, String[] words) { List<String> result = new ArrayList<>(); if (words == null || words.length == 0 || board == null || board.length == 0 || board[0].length == 0) return result; Trie trie = new Trie(); for (String temp : words) trie.insert(temp); TrieNode root = trie.root; boolean[][] visited = new boolean[board.length][board[0].length]; Set<String> tempResult = new HashSet<>(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < board.length; i++) { for (int j = 0; j < board[0].length; j++) { if (root.children[board[i][j] - 'a'] != null ) { dfs(board, visited, i, j, root.children[board[i][j] - 'a'], tempResult, sb); } } } // You need to copy the tempResult set to the real result List for return Iterator<String> iterator = tempResult.iterator(); while (iterator.hasNext()) { result.add(iterator.next()); } return result; } private void dfs(char[][] board, boolean[][] visited, int startIInBoard, int startJInBoard , TrieNode curNode, Set<String> resultSet, StringBuilder curStrBuilder) { curStrBuilder.append(board[startIInBoard][startJInBoard]); visited[startIInBoard][startJInBoard] = true; if (curNode.isEndOfWord) { resultSet.add(curStrBuilder.toString()); } // Search up if the grid above has not been searched if (startIInBoard > 0 && !visited[startIInBoard - 1][startJInBoard] && curNode.children[board[startIInBoard - 1][startJInBoard] - 'a'] != null) { dfs(board, visited,startIInBoard - 1, startJInBoard , curNode.children[board[startIInBoard - 1][startJInBoard] - 'a'], resultSet, curStrBuilder); } // Downward search if (startIInBoard < board.length - 1 && !visited[startIInBoard + 1][startJInBoard] && curNode.children[board[startIInBoard + 1][startJInBoard] - 'a'] != null) { dfs(board, visited,startIInBoard + 1, startJInBoard , curNode.children[board[startIInBoard + 1][startJInBoard] - 'a'], resultSet, curStrBuilder); } // Search left if (startJInBoard > 0 && !visited[startIInBoard][startJInBoard - 1] && curNode.children[board[startIInBoard][startJInBoard - 1] - 'a'] != null) { dfs(board, visited, startIInBoard, startJInBoard - 1 , curNode.children[board[startIInBoard][startJInBoard - 1] - 'a'], resultSet, curStrBuilder); } // Search right if (startJInBoard < board[0].length - 1 && !visited[startIInBoard][startJInBoard + 1] && curNode.children[board[startIInBoard][startJInBoard + 1] - 'a'] != null) { dfs(board, visited, startIInBoard, startJInBoard + 1 , curNode.children[board[startIInBoard][startJInBoard + 1] - 'a'], resultSet, curStrBuilder); } // Restore scene curStrBuilder.setLength(curStrBuilder.length() - 1); visited[startIInBoard][startJInBoard] = false; } }