Leetcode之回溯法专题-212. 单词搜索 II(Word Search II)

Leetcode之回溯法专题-212. 单词搜索 II(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(前缀树)

    


分析:题中提示里写前缀树可以解这题,但我做的时候没看到,硬用回溯+DFS做出来的,时间复杂度很高,二刷的时候再优化吧。

79题的升级版,同样也是地图题,需要vis数组来控制,具体见79题

class Solution {
    List<String> ans = new ArrayList<>();
    int dirx[] = new int[]{0,0,1,-1};
    int diry[] = new int[]{1,-1,0,0};
    int vis[][] = null;
    public List<String> findWords(char[][] board, String[] words) {
        vis = new int[board.length][board[0].length];
        
        List<String> list = Arrays.asList(words);
        int maxLen = getMaxLen(list);
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[0].length; j++) {
                if(list.size()!=0){
                    vis[i][j] = 1;
                    dfs(board,list,i,j,vis,board[i][j]+"",maxLen);
                    vis[i][j] = 0;
                }
            }
        }
        
        return ans;
    }
    
    public void dfs(char[][] board,List<String> words,int x,int y,int[][] vis,String now,int maxLen){
        if(now.length()>maxLen){
            return;
        }
        
        if(words.contains(now) && !ans.contains(now)){
            ans.add(now);
        }
        if(!hasPrefix(now, words)){
            return;
        }
        
        for(int i=0;i<4;i++){
            int xx = x + dirx[i];
            int yy = y + diry[i];
            
            if(xx>=0 && xx<board.length && yy>=0 && yy<board[0].length && vis[xx][yy]==0){
                vis[xx][yy] = 1;
                
                dfs(board,words,xx,yy,vis,now+board[xx][yy],maxLen);
                
                vis[xx][yy] = 0;
            }
        }
    }
    
    public int getMaxLen(List<String> list){
        int max = 0;
        if(list.size()==0) return 0;
        for (String string : list) {
            max = Math.max(max, string.length());
        }
        return max;
        
    }
    
    public boolean hasPrefix(String prefix,List<String> list){
        int len = prefix.length();
        for (String string : list) {
            if(string.length()>=len && string.substring(0, len).equals(prefix)){
                return true;
            }
        }
        
        
        return false;
    }
}

猜你喜欢

转载自www.cnblogs.com/qinyuguan/p/11330207.html