leetcode 212. 单词搜索 II 字典树+深度优先搜索 java代码 详细解释

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Viscu/article/details/82470435

给定一个二维网格 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”]
说明:
你可以假设所有输入都由小写字母 a-z 组成。

这道题目利用字典树进行深搜是可以大大加快效率的。
我们利用字典数来存下words里面的所有单词,在dfs搜索的时候,我们只需要对字典树里的单词
存在的向下检索即可。若不存在可以直接返回。
字典树,不懂的可以学一下,用处挺大的,ac自动机啥的就是字典树的延伸。

class Solution {
    public int[] dx={1,-1,0,0};
    public int[] dy={0,0,1,-1};
    private static class Trie{  //字典树
        String word;  //单词结束标志,到这里说明已经可以组成一个单词了。
        Trie[] next=new Trie[26]; //每个节点都有26个节点
        Trie append(char ch){  //拼接字符
            if(next[ch-'a']!=null){ 
                return next[ch-'a']; //有则直接返回节点
            }
            next[ch-'a']=new Trie(); //没有就新建节点
            return next[ch-'a'];
        }
    }
    public boolean[][] vis;  //判断是否参观过
    public List<String> res; 

    public List<String> findWords(char[][] board, String[] words) {
        Trie root=new Trie();
        for(String word:words){  //先把单词存入字典树当中
            Trie cur=root;
            char[] wd=word.toCharArray();
            for(char c:wd){
                cur=cur.append(c);
            }
            cur.word=word;  //结束标志,说明到这里已经可以组成一个单词
        }
        res=new ArrayList<String>();
        vis=new boolean[board.length][board[0].length];
        for(int i=0;i<board.length;++i){  //对board每一个点都进行检索
            for(int j=0;j<board[i].length;++j){
                dfs(root,i,j,board);
            }
        }
        Collections.sort(res);  //需要对结果进行排序
        return new ArrayList<String>(res);
    }

    public void dfs(Trie cur,int x,int y,char[][] board){
        if(x<0||y<0||x>=board.length||y>=board[0].length||vis[x][y]){
            return;
        } //边界返回
        cur=cur.next[board[x][y]-'a'];  //延伸下一个节点
        vis[x][y]=true; //把当前设置为走过 不可重复走
        if(cur!=null){ //如果当前不为null的话 可以继续检索
            if(cur.word!=null){ //说明到这里已经可以组成一个单词了
                res.add(cur.word); 
                cur.word=null; //变成null是为了防止重复加入单词
            }
            for(int i=0;i<4;++i){
                dfs(cur,x+dx[i],y+dy[i],board); //四个方向检索
            }
        }
        vis[x][y]=false; 
    }
}

猜你喜欢

转载自blog.csdn.net/Viscu/article/details/82470435
今日推荐