212. Word Search II
一、题目
1、审题
2、分析
给出一个二维字符矩阵 board,一个字符串数组 words。求出矩阵中连续的字符能组成的 words 中的单词,一个单词只能用同一个位置的字符一次。
二、解答
1、思路:
采用 Trie 字典树。
①、根据 words 创建 一个 Trie
②、遍历 board,以每个字符为起始字符,在 Trie 中以 DFS 查找是否存在此 word
1 class Solution { 2 public List<String> findWords(char[][] board, String[] words) { 3 List<String> result = new ArrayList<String>(); 4 // 1、构造查找字典 5 TrieNode root = buildTrie(words); 6 7 // 2、 从每一个字符开始 dfs 查找是否有存在的单词 8 for (int i = 0; i < board.length; i++) { 9 for (int j = 0; j < board[0].length; j++) { 10 dfs(board, i, j, root, result); 11 } 12 } 13 14 return result; 15 } 16 17 private void dfs(char[][] board, int i, int j, TrieNode node, 18 List<String> result) { 19 char c = board[i][j]; 20 if(c == '#' || node.children[c - 'a'] == null) 21 return; 22 node = node.children[c - 'a']; 23 if(node.word != null) { // found one 24 result.add(node.word); 25 node.word = null; 26 } 27 28 board[i][j] = '#'; 29 if(i > 0) 30 dfs(board, i - 1, j, node, result); 31 if(j > 0) 32 dfs(board, i, j - 1, node, result); 33 if(i < board.length - 1) 34 dfs(board, i + 1, j, node, result); 35 if(j < board[0].length - 1) 36 dfs(board, i, j + 1, node, result); 37 board[i][j] = c; 38 } 39 40 private TrieNode buildTrie(String[] words) { 41 TrieNode root = new TrieNode(); 42 for(String word: words) { 43 TrieNode node = root; 44 for(char c: word.toCharArray()) { 45 int i = c - 'a'; 46 if(node.children[i] == null) 47 node.children[i] = new TrieNode(); 48 node = node.children[i]; 49 } 50 node.word = word; 51 } 52 return root; 53 } 54 } 55 56 class TrieNode { 57 public boolean isWord; 58 public TrieNode[] children = new TrieNode[26]; 59 public String word; 60 61 }
2、方法二,不使用字典树。采用一个 Boolean 数组记录当前位置是否访问过。
public List<String> findWords(char[][] board, String[] words) { int rows = board.length; int cols = board[0].length; List<String> result = new ArrayList<String>(); boolean[][] IS_USED = new boolean[rows][cols]; for(String word: words) { for (int row = 0; row < rows; row++) { for (int col = 0; col < cols; col++) { char[] cArray = word.toCharArray(); if(is_pattered(board, row, col, rows, cols, IS_USED, 0, word.length() - 1, cArray)) result.add(word); } } } return new ArrayList<String>(new HashSet<String>(result)); } private boolean is_pattered(char[][] board, int row, int col, int rows, int cols, boolean[][] iS_USED, int start, int end, char[] cArray) { if(start > end) return true; if(row >= rows || col >= cols || row < 0 || col < 0) return false; if(board[row][col] != cArray[start] || iS_USED[row][col] == true) return false; iS_USED[row][col] = true; if(is_pattered(board, row + 1, col, rows, cols, iS_USED, start + 1, end, cArray) || is_pattered(board, row - 1, col, rows, cols, iS_USED, start + 1, end, cArray) || is_pattered(board, row, col + 1, rows, cols, iS_USED, start + 1, end, cArray) || is_pattered(board, row, col - 1, rows, cols, iS_USED, start + 1, end, cArray) ) { iS_USED[row][col] = false; // 恢复 return true; } iS_USED[row][col] = false; return false; }