package class26; import java.util.ArrayList; import java.util.HashSet; import java.util.LinkedList; import java.util.List; // 本题测试链接 : https://leetcode.com/problems/word-search-ii/ public class Code02_WordSearchII { public static class TrieNode { public TrieNode[] nexts; public int pass; public boolean end; public TrieNode() { nexts = new TrieNode[26]; pass = 0; end = false; } } public static void fillWord(TrieNode head, String word) { head.pass++; char[] chs = word.toCharArray(); int index = 0; TrieNode node = head; for (int i = 0; i < chs.length; i++) { index = chs[i] - 'a'; if (node.nexts[index] == null) { node.nexts[index] = new TrieNode(); } node = node.nexts[index]; node.pass++; } node.end = true; } public static String generatePath(LinkedList path) { char[] str = new char[path.size()]; int index = 0; for (Character cha : path) { str[index++] = cha; } return String.valueOf(str); } public static List findWords(char[][] board, String[] words) { TrieNode head = new TrieNode(); // 前缀树最顶端的头 HashSet set = new HashSet<>(); for (String word : words) { if (!set.contains(word)) { fillWord(head, word); set.add(word); } } // 答案 List ans = new ArrayList<>(); // 沿途走过的字符,收集起来,存在path里 LinkedList path = new LinkedList<>(); for (int row = 0; row < board.length; row++) { for (int col = 0; col < board[0].length; col++) { // 枚举在board中的所有位置 // 每一个位置出发的情况下,答案都收集 process(board, row, col, path, head, ans); } } return ans; } // 从board[row][col]位置的字符出发, // 之前的路径上,走过的字符,记录在path里 // cur还没有登上,有待检查能不能登上去的前缀树的节点 // 如果找到words中的某个str,就记录在 res里 // 返回值,从row,col 出发,一共找到了多少个str public static int process( char[][] board, int row, int col, LinkedList path, TrieNode cur, List res) { char cha = board[row][col]; if (cha == 0) { // 这个row col位置是之前走过的位置 return 0; } // (row,col) 不是回头路 cha 有效 int index = cha - 'a'; // 如果没路,或者这条路上最终的字符串之前加入过结果里 if (cur.nexts[index] == null || cur.nexts[index].pass == 0) { return 0; } // 没有走回头路且能登上去 cur = cur.nexts[index]; path.addLast(cha);// 当前位置的字符加到路径里去 int fix = 0; // 从row和col位置出发,后续一共搞定了多少答案 // 当我来到row col位置,如果决定不往后走了。是不是已经搞定了某个字符串了 if (cur.end) { res.add(generatePath(path)); cur.end = false; fix++; } // 往上、下、左、右,四个方向尝试 board[row][col] = 0; if (row > 0) { fix += process(board, row - 1, col, path, cur, res); } if (row < board.length - 1) { fix += process(board, row + 1, col, path, cur, res); } if (col > 0) { fix += process(board, row, col - 1, path, cur, res); } if (col < board[0].length - 1) { fix += process(board, row, col + 1, path, cur, res); } board[row][col] = cha; path.pollLast(); cur.pass -= fix; return fix; } }