给定一个 m x n 二维字符网格 board 和一个单词(字符串)列表 words,找出所有同时在二维网格和字典中出现的单词。
单词必须按照字母顺序,通过 相邻的单元格 内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。
Tire树 + 哈希表
class Solution { //构造结点 class TreeNode{ String s; //记录当前结尾字符为s TreeNode tns[] = new TreeNode[26]; } TreeNode root = new TreeNode(); //根结点 //实现Trie插入单词 public void insert(String word) { TreeNode p = root; for (char c: word.toCharArray()) { int u = c - 'a'; if (p.tns[u] == null) { p.tns[u] = new TreeNode(); } p = p.tns[u]; } p.s = word; } //标记走过的 boolean[][] vis = new boolean[15][15]; //哈希表去重 Set<String> set = new HashSet<>(); public List<String> findWords(char[][] board, String[] words) { int m = board.length, n = board[0].length; //构造Trie树 for (String s: words) { insert(s); } //枚举起点 for (int i = 0; i < m; i ++ ) { for (int j = 0; j < n; j ++ ) { int u = board[i][j] - 'a'; //要有该起点在Trie上有分支才进行枚举 if (root.tns[u] != null ) { vis[i][j] = true; //标记走过 dfs(board, i, j, root.tns[u]); vis[i][j] = false; } } } List<String> res = new ArrayList<>(); for (String word: set) { res.add(word); } return res; } public void dfs(char[][] board, int i, int j, TreeNode p) { //当前字符已经是结尾那个,就装入结果集 if (p.s != null) set.add(p.s); int dx[] = new int[]{0, 1, 0, -1}; int dy[] = new int[]{1, 0, -1 ,0}; //枚举四个方向 for (int d = 0; d < 4; d ++ ) { int a = i + dx[d], b = j + dy[d]; if (a < 0 || b < 0 || a >= board.length || b >= board[0].length || vis[a][b] == true) continue; int u = board[a][b] - 'a'; //只有在Trie上存在分支,才往下走 if (p.tns[u] != null) { vis[a][b] = true; dfs(board, a, b, p.tns[u]); vis[a][b] = false; } } } }