LeetCode第212题单词搜索 II

题目:

给定一个 m x n 二维字符网格 board 和一个单词(字符串)列表 words,找出所有同时在二维网格和字典中出现的单词。

单词必须按照字母顺序,通过 相邻的单元格 内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。

示例 1:

输入:board = [["o","a","a","n"],["e","t","a","e"],["i","h","k","r"],["i","f","l","v"]], words = ["oath","pea","eat","rain"]
输出:["eat","oath"]

示例 2:

输入:board = [["a","b"],["c","d"]], words = ["abcb"]
输出:[]

提示:

    m == board.length n == board[i].length 1 <= m, n <= 12 board[i][j] 是一个小写英文字母 1 <= words.length <= 3 * 104 1 <= words[i].length <= 10 words[i] 由小写英文字母组成 words 中的所有字符串互不相同

思路:前缀树+dfs

如果给我们一个二维字符网格和一个字符串,然我们检查字符串是否在二维网格中出现,我们可以很容易写出,先遍历二维网格,如果有和字符串开头相同的字符则使用dfs查找是否存在。题目中给出的是一个字符串列表,我们需要考虑如何快速在这个列表中出以这个字符开头的字符串,显而易见我们可以使用字典序查找。

具体算法:

    先构建一颗字典树 然后在使用dfs查找
class Solution {
          
   
    public class TrieTree{
          
   
        TrieTree[] next;
        String end;

        public TrieTree(){
          
   
            next = new TrieTree[26];
            end = null;
        }
    }

    public List<String> findWords(char[][] board, String[] words) {
          
   
        List<String> ans = new ArrayList<>();

        if(board.length == 0 || board[0].length == 0) return ans;

        TrieTree root = new TrieTree();
        TrieTree p = root;

        // 构建前缀树
        int n = words.length;
        for(int i = 0; i < n; i++) {
          
   
            p = root;
            for(int j = 0; j < words[i].length(); j++) {
          
   
                int ind = words[i].charAt(j) - a;
                if(p.next[ind] == null) p.next[ind] = new TrieTree();
                p = p.next[ind];
            }
            p.end = words[i];
        }

        n = board.length;
        int m = board[0].length;
        is = new boolean[n][m];
        for(int i = 0; i < n; i++) {
          
   
            for(int j = 0; j < m; j++) {
          
   
                if(root.next[board[i][j] - a] != null) {
          
   
                    check(root, board, i, j, ans, n, m);
                }
            }
        }

        return ans;
    }

    boolean[][] is;

    private void check(TrieTree root, char[][] board, int i, int j, List<String> ans, int n, int m) {
          
   
        if(i < 0 || j < 0 || i >= n || j >= m || is[i][j] || root.next[board[i][j] - a] == null) return;
        int ind = board[i][j] - a;
        if(root.next[ind].end != null) {
          
   
            ans.add(root.next[ind].end);
            root.next[ind].end = null;
        }
        is[i][j] = true;
        check(root.next[ind], board, i + 1, j, ans, n, m);
        check(root.next[ind], board, i - 1, j, ans, n, m);
        check(root.next[ind], board, i, j + 1, ans, n, m);
        check(root.next[ind], board, i, j - 1, ans, n, m);
        is[i][j] = false;
    }
}
经验分享 程序员 微信小程序 职场和发展