leetcode 212. 单词搜索 II

链接: leetcode
给定一个二维网格 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

class TrieNode{
    public int path;//路过
    public int end;//结尾
    public TrieNode[] next;
    
    public TrieNode(){
        path = 0;
        end = 0;
        next = new TrieNode[26];
    }
}
class Trie {

    /** Initialize your data structure here. */
    TrieNode root;
    public Trie() {
        root = new TrieNode();
    }
    
    /** Inserts a word into the trie. */
    public void insert(String word) {
        char[] chars = word.toCharArray();
        TrieNode cur = root;
        for(int i = 0;i < chars.length;i++){
            int cnt = chars[i]- 'a';
            if(cur.next[cnt] == null){
                TrieNode node = new TrieNode();
                cur.next[cnt] = node;
                node.path++;
            }
            cur = cur.next[cnt];
        }
        cur.end++;

    }
    
    /** Returns if the word is in the trie. */
    public boolean search(String word) {
        char[] chars = word.toCharArray();
        TrieNode cur = root;
        for(int i = 0;i < chars.length;i++){
            int cnt = chars[i]- 'a';
            if(cur.next[cnt] == null){
                return false;
            }
            cur = cur.next[cnt];
        }
        if(cur.end>0)
            return true;
        else
            return false;
    }
    
    /** Returns if there is any word in the trie that starts with the given prefix. */
    public boolean startsWith(String word) {
        char[] chars = word.toCharArray();
        TrieNode cur = root;
        for(int i = 0;i < chars.length;i++){
            int cnt = chars[i]- 'a';
            if(cur.next[cnt] == null){
                return false;
            }
            cur = cur.next[cnt];
        }
        if(cur.end>0 || cur.path>0)
            return true;
        else
            return false;
    }
}
class Solution {
    int n,m;
    Trie trie;
    int[] dx = {-1,0,1,0};
    int[] dy = {0,1,0,-1};
    Set<String> ans = new HashSet<>();
    boolean[][] vis;
    char[][] board;
    public List<String> findWords(char[][] board1, String[] words) {
        trie = new Trie();
        n = board1.length;
        m = board1[0].length;
        board = board1;
        vis = new boolean[n][m];
        for(String word:words)
            trie.insert(word);
        for(int i = 0;i < n;i++){
            for(int j = 0;j<m;j++){
                if(trie.startsWith(String.valueOf(board[i][j])))
                    dfs(i,j,new StringBuilder());
            }
        }
        return new ArrayList(ans);
    }
    public void dfs(int x,int y,StringBuilder cur){  
        vis[x][y] = true;
        cur.append(board[x][y]);
        
        String tmp = cur.toString();
        
        if(trie.search(tmp))
            ans.add(tmp);
        
        if(!trie.startsWith(tmp)){
             cur.deleteCharAt(cur.length()-1);
             vis[x][y] = false;
            return;
        }
        
        for(int i = 0;i < 4;i++){
            int nx = x+dx[i];
            int ny = y+dy[i];
            if(nx>=0 && nx < n && ny>=0 && ny < m && !vis[nx][ny]){
                dfs(nx,ny,cur);
            }
        }
        cur.deleteCharAt(cur.length()-1);
        vis[x][y] = false;
        
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值