212. Word Search II(单词搜索II)

题目链接: https://leetcode.com/problems/word-search-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(前缀树)。

思路一:

普通回溯法,从字典中依次取出每一个单词,然后碰到board中有首字母相同的就记入回溯。

缺点是回溯速度较慢。

AC 417ms

class Solution {
    Set<String> set=new HashSet();
    public List<String> findWords(char[][] board, String[] words) {
        if(board==null||board.length==0||board[0].length==0)
            return new ArrayList<String>();
        for(String str:words){
            char c=str.charAt(0);
            char[] cur=str.toCharArray();
            for(int i=0;i<board.length;i++){
                for(int j=0;j<board[0].length;j++){
                    if(board[i][j]==c){
                        boolean[][] isVisited=new boolean[board.length][board[0].length];
                        backtrace(board,cur,0,i,j,isVisited);
                    }   
                }
            }
        }
        return new ArrayList(set);
    }
    public void backtrace(char[][] board,char[] cur,int index,int i,int j,boolean[][] isVisited){
        if(i<0||j<0||i>=board.length||j>=board[0].length
           ||index>=cur.length||isVisited[i][j]==true||board[i][j]!=cur[index])
            return;
        isVisited[i][j]=true;
        if(index==cur.length-1)
            set.add(String.valueOf(cur));
        backtrace(board,cur,index+1,i,j+1,isVisited);
        backtrace(board,cur,index+1,i+1,j,isVisited);
        backtrace(board,cur,index+1,i,j-1,isVisited);
        backtrace(board,cur,index+1,i-1,j,isVisited);
        isVisited[i][j]=false;
    }
}

思路二:

利用trie树来构建,这样可以优化回溯的重复情形。

AC 9ms:

class TrieNode{
    TrieNode[] children=new TrieNode[26];
    String word;
}
class Solution {
    List<String> ans=new ArrayList();
    public List<String> findWords(char[][] board, String[] words) {
        if(board==null||board.length==0||board[0].length==0)
            return ans;
        TrieNode root=buildTrie(words);
        for(int i=0;i<board.length;i++){
            for(int j=0;j<board[0].length;j++){
                boolean[][] isVisited=new boolean[board.length][board[0].length];
                backtrack(board,i,j,root,isVisited);
            }
        }
        return ans;
    }
    public void backtrack(char[][] board,int i,int j,TrieNode temp,boolean[][] isVisited){
        if(i<0||j<0||i>=board.length||j>=board[0].length
           ||isVisited[i][j]==true||temp.children[board[i][j]-'a']==null)
            return;
        isVisited[i][j]=true;
        temp=temp.children[board[i][j]-'a'];
        if(temp.word!=null){
            ans.add(temp.word);
            temp.word=null;
        }
        backtrack(board,i,j+1,temp,isVisited);
        backtrack(board,i+1,j,temp,isVisited);
        backtrack(board,i,j-1,temp,isVisited);
        backtrack(board,i-1,j,temp,isVisited);
        isVisited[i][j]=false;
    }
    public TrieNode buildTrie(String[] words){
        TrieNode root=new TrieNode();
        for(String word : words){
            TrieNode temp=root;
            for(char c:word.toCharArray()){
                int i=c-'a';
                if(temp.children[i]==null){
                    temp.children[i]=new TrieNode();
                }
                temp=temp.children[i];
            }
            temp.word=word;
        }
     return root;
    }
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值