0
点赞
收藏
分享

微信扫一扫

【leetcode-字符串】单词搜索 II


题目:

给定一个二维网格 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 组成。

提示:

  • 你需要优化回溯算法以通过更大数据量的测试。你能否早点停止回溯?
  • 如果当前单词不存在于所有单词的前缀中,则可以立即停止回溯。什么样的数据结构可以有效地执行这样的操作?散列表是否可行?为什么? 前缀树如何?如果你想学习如何实现一个基本的前缀树,请先查看这个问题: 实现Trie(前缀树)。

思路:

题目给了提示利用回溯法,如果当前单词不存在于所有单词的前缀中,则可以立即停止回溯。什么样的数据结构可以有效地执行这样的操作?散列表是否可行?为什么? 前缀树如何?如果你想学习如何实现一个基本的前缀树,请先查看这个问题:原创 【leetcode-字符串】实现 Trie (前缀树)

 

java代码:

class Solution {
    private static class Trie {
        String word;  //单词结束标志,到这里说明已经可以组成一个单词了。

        Trie[] next = new Trie[26]; //每个节点都有26个节点

        Trie append(char ch) {
            if (next[ch - 'a'] == null) {
                next[ch - 'a'] = new Trie();
            }
            return next[ch - 'a'];
        }
    }

    private boolean[][] visited; //判断是否参加过
    List<String> res = new ArrayList<>();

    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>();
        visited=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||visited[x][y]){
            return;
        } //边界返回
        cur=cur.next[board[x][y]-'a'];  //延伸下一个节点
        visited[x][y]=true; //把当前设置为走过 不可重复走
        if(cur!=null){ //如果当前不为null的话 可以继续检索
            if(cur.word!=null){ //说明到这里已经可以组成一个单词了
                res.add(cur.word);
                cur.word=null; //变成null是为了防止重复加入单词
            }

            dfs(cur,x+1,y,board); //四个方向检索
            dfs(cur,x-1,y,board); //四个方向检索
            dfs(cur,x,y+1,board); //四个方向检索
            dfs(cur,x,y-1,board); //四个方向检索

        }
        visited[x][y]=false; //回溯,把visited置为false,供一个单词匹配时用
    }
}

 

举报

相关推荐

0 条评论