给定一个二维网格 board 和一个字典中的单词列表 words,找出所有同时在二维网格和字典中出现的单词。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。
示例:
输入: words =["oath","pea","eat","rain"]
and board = [ ['o','a','a','n'], ['e','t','a','e'], ['i','h','k','r'], ['i','f','l','v'] ] 输出:["eat","oath"]
思路:
1、要打印所有情况,因此进行dfs,单词不允许重复,使用Set存储结果
2、将字典词存到字典树中
3、以二维数组每一个元素为单词第一个字母去遍历字典树,二维数组中的延伸方向为上下左右,使用visit数组保存是否访问过节点,使用数组边界判断避免越界
4、在dfs过程中判断单词所在字典树的节点end属性是否为true,为true添加该节点,继续dfs
5、dfs结束条件为树节点为null,返回false;
class Solution {
//构建trie树节点
public class TrieNode{
private Map<Character,TrieNode> map = new HashMap<>();
private boolean end;
public TrieNode getSubNode(Character key){
return map.get(key);
}
public void addSubNode(Character key,TrieNode value){
map.put(key,value);
}
public boolean containsNode(Character key){
return map.containsKey(key);
}
public boolean isEnd(){
return end;
}
public void setEnd(boolean end){
this.end=end;
}
}
public List<String> findWords(char[][] board, String[] words) {
TrieNode root=new TrieNode();
root = insertWord(root,words);
List<String> list = new ArrayList<>();
Set<String> set = new HashSet<>();
StringBuilder sb = new StringBuilder();
boolean[][] visit = new boolean[board.length][board[0].length];
int count=0;
for(int i=0;i<board.length;i++){
for(int j=0;j<board[0].length;j++){
searchWords(i,j,root,board,set,sb,visit);
}
}
for(String s:set){
list.add(s);
}
return list;
}
//插入字典单词到trie树
public TrieNode insertWord(TrieNode root,String[] words){
TrieNode tmpNode = root;
for(int i=0;i<words.length;i++){
tmpNode=root;
for(int j=0;j<words[i].length();j++){
char c = words[i].charAt(j);
TrieNode node = tmpNode.getSubNode(c);
if(node==null){
node=new TrieNode();
tmpNode.addSubNode(c,node);
}
tmpNode=node;
if(j==words[i].length()-1){tmpNode.setEnd(true);}
}
}
return root;
}
public boolean searchWords(int i,int j,TrieNode node,char[][] board,Set<String> list,StringBuilder sb,boolean[][] visit){
boolean success=false;
TrieNode tmpNode = node.getSubNode(board[i][j]);
if(tmpNode==null){
return false;
}else{
sb.append(board[i][j]);
visit[i][j]=true;
if(tmpNode.isEnd()){
list.add(new String(sb));
}
if((i>0&&!visit[i-1][j])&&!success){
success=searchWords(i-1,j,tmpNode,board,list,sb,visit);
}
if((i<board.length-1&&!visit[i+1][j])&&!success){
success=searchWords(i+1,j,tmpNode,board,list,sb,visit);
}
if((j>0&&!visit[i][j-1])&&!success){
success=searchWords(i,j-1,tmpNode,board,list,sb,visit);
}
if((j<board[0].length-1&&!visit[i][j+1])&&!success){
success=searchWords(i,j+1,tmpNode,board,list,sb,visit);
}
sb.delete(sb.length()-1,sb.length());
visit[i][j]=false;
}
return false;
}
}