单词搜索 II——leetcode212(DFS/DFS+字典树)
单词搜索 II
题目:单词搜索 II
给定一个 m x n
二维字符网格 board
和一个单词(字符串)列表 words
,找出所有同时在二维网格和字典中出现的单词。
单词必须按照字母顺序,通过 相邻的单元格 内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。
示例:
输入:board = [["o","a","a","n"],["e","t","a","e"],["i","h","k","r"],["i","f","l","v"]], words = ["oath","pea","eat","rain"]
输出:["eat","oath"]
题解
方法一: 单纯的DFS
会超时
方法二:DFS+前缀剪枝
用set集合存储字典中的前缀
dfs遍历时判断当前字符串在前缀结合中是否存在
如果存在,则继续,否则就退出。
时间复杂度和空间复杂度:10%
class Solution0 {
private Set<String> results;
private Set<String> prex;
private Set<String> wordSet;
private int[][] nag=new int[][]{{0,1},{0,-1},{-1,0},{1,0}};
public void dfs(char[][] board, int[][] book, int x, int y, StringBuilder sb){
if(!prex.contains(sb.toString())) return; //判断前缀中是否包含sb
if(wordSet.contains(sb.toString())) { //判断结果中是否包含sb
results.add(sb.toString());
}
for(int i=0;i<4;i++) {
int newx=x+nag[i][0], newy=y+nag[i][1];
if(newx<0 || newx>=board.length || newy<0 || newy>=board[0].length || book[newx][newy]==1) continue;
book[newx][newy]=1;
sb.append(board[newx][newy]);
dfs(board, book, newx, newy, sb);
sb.deleteCharAt(sb.length()-1);
book[newx][newy]=0;
}
}
public List<String> findWords(char[][] board, String[] words) {
int[][] book=new int[board.length][board[0].length];
results=new HashSet<>();
prex=new HashSet<>(); //前缀集合
wordSet=new HashSet<>(); //字典集合
for(int i=0;i<words.length;i++) {
for(int j=0;j<words[i].length();j++){
prex.add(words[i].substring(0, j+1));
}
wordSet.add(words[i]);
}
StringBuilder sb=new StringBuilder();
for(int i=0;i<board.length;i++) {
for(int j=0;j<board[0].length;j++) {
book[i][j]=1;
sb.append(board[i][j]);
dfs(board, book, i, j, sb);
sb.deleteCharAt(sb.length()-1);
book[i][j]=0;
}
}
return new ArrayList<>(results);
}
}
方法三:DFS+字典树
class Solution {
class Tree
{
String word;
Map<Character, Tree> children;
public Tree()
{
this.word="";
children=new HashMap<>();
}
//字典树插入
public void insert(String word){
Tree temp=this;
for(int i=0;i<word.length();i++) {
char c=word.charAt(i);
temp.children.putIfAbsent(c, new Tree());
temp=temp.children.get(c);
}
temp.word=word;
}
}
private Set<String> results;
private int[][] dirs=new int[][]{{1,0},{-1,0},{0,1},{0,-1}};
public void dfs(char[][] board, Tree root, int x, int y, int[][] book) {
//字典树:判断board[x][y]是否是当前节点的下一个节点
if(!root.children.containsKey(board[x][y])) return;
Tree next=root.children.get(board[x][y]);
//判断当前节点是否是叶子节点
if(!next.word.equals("")){
results.add(next.word);
}
//DFS遍历四个方向的节点
for(int i=0;i<4;i++){
int newx=x+dirs[i][0], newy=y+dirs[i][1];
if(newx<0||newx>=board.length|| newy<0|| newy>=board[0].length || book[newx][newy]==1) continue;
book[newx][newy]=1;
dfs(board, next, newx, newy, book);
book[newx][newy]=0;
}
}
public List<String> findWords(char[][] board, String[] words) {
results=new HashSet<>();
int book[][]=new int[board.length][board[0].length];
Tree root=new Tree();
for (String word : words) {
root.insert(word);
}
StringBuilder sb=new StringBuilder();
for(int i=0;i<board.length;i++){
for(int j=0;j<board[0].length;j++) {
book[i][j]=1;
dfs(board, root, i, j, book);
book[i][j]=0;
}
}
return new ArrayList<>(results);
}
}