LintCode 单词搜索Ⅱ 字典树
今天做了道有意思的题目,题目要解出来不难,但看到他的提示
发现这道题我一开始并没有用到字典树
然后就使用字典树+DFS写了一遍,也算是巩固下字典树的相关知识
题目:原题地址
给出一个由小写字母组成的矩阵和一个字典。找出所有同时在字典和矩阵中出现的单词。一个单词可以从矩阵中的任意位置开始,可以向左/右/上/下四个相邻方向移动。
样例
给出矩阵:
doaf
agai
dcan
和字典:
{"dog", "dad", "dgdg", "can", "again"}
返回 {"dog", "dad", "can", "again"}
挑战
使用单词查找树来实现你的算法
解题思路:
先对给的字典建立一颗字典树,然后使用DFS在给的矩阵内搜索字典树,相关注释现在了代码里。
下面贴代码:
package ww; import java.util.ArrayList; import java.util.Arrays; import org.junit.Test; public class TestDC { @Test //测试用例 //输出:[dog, dad, again, can] public void test() { char[][] board = { { 'd', 'o', 'a', 'f' }, { 'a', 'g', 'a', 'i' }, { 'd', 'c', 'a', 'n' } }; ArrayList<String> list = new ArrayList<String>(); String[] tem = { "dog", "dad", "dgdg", "can", "again" }; for (String tt : tem) { list.add(tt); } ArrayList<String> wordSearchII = wordSearchII(board, list); System.out.println(wordSearchII); } int MAX_N = 1000000;//字典树最大深度 int MAX_C = 26;//表示26个小写字母 int tot = 0;//用于记录位置 String[] ch;//用来标记结尾的字母所对应的单词 int[][] cnt;//用来表示字典树 //初始化字典树 public void init() { ch = new String[MAX_N]; cnt = new int[MAX_N][]; Arrays.fill(ch, null); Arrays.fill(cnt, null); } //构建字典树 public void insert(String str) { int p = 0; for (char ch : str.toCharArray()) { if (cnt[p] == null) { cnt[p] = new int[MAX_C]; Arrays.fill(cnt[p], -1); } /** * 表示该单词下一个字母应对应的位置 */ if (cnt[p][ch - 'a'] == -1) { cnt[p][ch - 'a'] = ++tot; } p = cnt[p][ch - 'a']; } //表示这个单词插入玩成,在字典树对应的最后一个字母上,标记这个单词,以便查找 if (ch[p] == null) { ch[p] = str; } } //支持1.8的话,使用下面的Stream去重。不支持的话使用HashSet去重 //原理相同 // public void dfsFind(char[][] board, boolean[][] visited, int row, int col, int p, HashSet<String> list) { // if (ch[p] != null) { // list.add(ch[p]); // } // if (row >= 0 && row < board.length && col >= 0 && col < board[0].length && visited[row][col] == false // && (cnt[p] != null) && (p = cnt[p][board[row][col] - 'a']) != -1) { // visited[row][col] = true; // // dfsFind(board, visited, row - 1, col, p, list); // dfsFind(board, visited, row, col + 1, p, list); // dfsFind(board, visited, row + 1, col, p, list); // dfsFind(board, visited, row, col - 1, p, list); // visited[row][col] = false; // // } // // } // // public ArrayList<String> wordSearchII(char[][] board, ArrayList<String> words) { // init(); // for (String str : words) { // insert(str); // } // boolean[][] visited = new boolean[board.length][board[0].length]; // HashSet<String> list = new HashSet<String>(); // for (int i = 0; i < board.length; i++) { // for (int j = 0; j < board[0].length; j++) { // dfsFind(board, visited, i, j, 0, list); // } // } // ArrayList<String> rl = new ArrayList<String>(); // Iterator<String> iterator = list.iterator(); // while (iterator.hasNext()) { // rl.add(iterator.next()); // } // return rl; // } //dfs搜索寻找单词 public void dfsFind(char[][] board, boolean[][] visited, int row, int col, int p, ArrayList<String> list) { //找到了,加入list if (ch[p] != null) { list.add(ch[p]); } //依次向4个方向搜索 if (row >= 0 && row < board.length && col >= 0 && col < board[0].length && visited[row][col] == false && (cnt[p] != null) && (p = cnt[p][board[row][col] - 'a']) != -1) { visited[row][col] = true; dfsFind(board, visited, row - 1, col, p, list); dfsFind(board, visited, row, col + 1, p, list); dfsFind(board, visited, row + 1, col, p, list); dfsFind(board, visited, row, col - 1, p, list); visited[row][col] = false; } } public ArrayList<String> wordSearchII(char[][] board, ArrayList<String> words) { init();//字典树的初始化 //构建字典树 for (String str : words) { insert(str); } //用于标记以走过的路程 boolean[][] visited = new boolean[board.length][board[0].length]; ArrayList<String> list = new ArrayList<String>(); //搜索 for (int i = 0; i < board.length; i++) { for (int j = 0; j < board[0].length; j++) { dfsFind(board, visited, i, j, 0, list); } } //去重 ArrayList<String> rl = new ArrayList<String>(); list.stream().distinct().forEach(rl::add); return rl; } }