212. 单词搜索 II
https://leetcode.cn/problems/word-search-ii/description/?envType=study-plan-v2&envId=top-interview-150
思路:
1. 我们可以先将这个单词网格转化成一颗字典树,然后再拿words进行搜索。
2. 我们可以先将words装换成字典树,然后在在board中选点看能不能走出一条满足的路径来
对于这两个思路其实差不多,但是1的话如果board太大就很容易超时,而且无用的构建会很多(比如有一个5*5的board,理论一条路径长度应该是25,但是如果words中长的单词都只有5的话我们就根本用不到这么长)。
所以权衡来看第二种思路会更好
思路一(确实会超时):
class Trie {Trie[] children;boolean isEnd;public Trie() {children = new Trie[26];isEnd = true; // 每个被构造出的节点都是一个单词的结尾}}public List<String> findWords(char[][] board, String[] words) {boolean[][] signed = new boolean[board.length][board[0].length];Trie root = new Trie();for(int i = 0; i < board.length; i++) {for(int j = 0; j < board[0].length; j++) {signed[i][j] = true;if(root.children[board[i][j] - 'a'] == null) {root.children[board[i][j] - 'a'] = new Trie();}transfer(board, signed, root.children[board[i][j] - 'a'], i, j);signed[i][j] = false;}}List<String> ans = new ArrayList<>();for(String word : words) {if(search(root, word)) {ans.add(word);}}return ans;}public void transfer(char[][] board, boolean[][] signed, Trie root, int x, int y) {for(int i = 0; i < 4; i++) {int xx = x + dx[i];int yy = y + dy[i];if(xx >= 0 && xx < board.length && yy >= 0 && yy < board[0].length && !signed[xx][yy]) {signed[xx][yy] = true;if(root.children[board[xx][yy] - 'a'] == null) root.children[board[xx][yy] - 'a'] = new Trie();transfer(board, signed, root.children[board[xx][yy] - 'a'], xx, yy);signed[xx][yy] = false;}}}
思路二:
class Trie {Trie[] children;String word; // 如果当前节点是不是一个单词的结尾,那么word=这个单词,否则word=""public Trie() {children = new Trie[26];word = "";}}public List<String> findWords(char[][] board, String[] words) {// 将words构建成字典树Trie root = new Trie();for(String word : words) {add(root, word);}boolean[][] signed = new boolean[board.length][board[0].length];HashSet<String> ans = new HashSet<>();// 在board中选取点在Tire中走看是否存在路径for(int i = 0; i < board.length; i++) {for(int j = 0; j < board[0].length; j++) {signed[i][j] = true;dfs(root, board, signed, ans, i, j);signed[i][j] = false;}}return new ArrayList<>(ans);}public void add(Trie root, String word) {for(int i = 0; i < word.length(); i++) {if(root.children[word.charAt(i) - 'a'] == null) {root.children[word.charAt(i) - 'a'] = new Trie();}root = root.children[word.charAt(i) - 'a'];}root.word = word;}/*** 深度优先搜索* @param root 当前节点* @param board 单词网格* @param signed 标记数组* @param ans 答案* @param x 当前位置x坐标* @param y 当前位置y坐标*/public void dfs(Trie root, char[][] board, boolean[][] signed, HashSet<String> ans, int x, int y) {if(root == null) return;if(!Objects.equals(root.word, "")) {ans.add(root.word);}root = root.children[board[x][y] - 'a'];for(int i = 0; i < 4; i++) {int xx = x + dx[i];int yy = y + dy[i];if(xx >= 0 && xx < board.length && yy >= 0 && yy < board[0].length && !signed[xx][yy]) {char ch = board[xx][yy];signed[xx][yy] = true;dfs(root, board, signed, ans, xx, yy);signed[xx][yy] = false;}}if (root != null && root.word != "") ans.add(root.word);}public boolean search(Trie root, String word) {for(int i = 0; i < word.length(); i++) {if(root.children[word.charAt(i) - 'a'] == null) {return false;}root = root.children[word.charAt(i) - 'a'];}return "".equals(root.word);}