212. 单词搜索 II

95 阅读1分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动

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"] 输出:[]

解题思路

使用前缀树保存单词列表,遍历二维网格的每一个元素,以其为起始节点,使用dfs匹配前缀树

代码

class Solution {
    class Trie {

        public Node root = new Node();

        public Trie() {

        }

        public void insert(String word) {
            Node cur = root;
            for (int i = 0; i < word.length(); i++) {
                if (cur.nodes[word.charAt(i) - 'a'] == null)
                    cur.nodes[word.charAt(i) - 'a'] = new Node();
                cur = cur.nodes[word.charAt(i) - 'a'];
            }
            cur.isEnd = true;
        }
    }

    class Node {
        Node[] nodes;
        boolean isEnd = false;

        public Node() {
            nodes = new Node[26];
        }
    }

    int[][] d = new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
    Set<String> strings = new HashSet<>();

    public List<String> findWords(char[][] board, String[] words) {

        StringBuilder sb = new StringBuilder();
        int n = board.length, m = board[0].length;
        boolean[][] ck = new boolean[n][m];
        Trie trie = new Trie();
        for (String c : words)
            trie.insert(c);
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++)
                dfsFindWords(board, i, j, sb, trie.root, ck);
        return new ArrayList(strings);
    }
        public void dfsFindWords(char[][] board, int x, int y, StringBuilder stringBuilder, Node th, boolean[][] check) {

        if (th.isEnd) strings.add(stringBuilder.toString());
        int cur = board[x][y] - 'a';
        if (th.nodes[cur] != null) {
            stringBuilder.append(board[x][y]);
            check[x][y] = true;
            for (int[] dd : d) {
                int nx = x + dd[0], ny = y + dd[1];
                if (nx < 0 || ny < 0 || nx >= board.length || ny >= board[0].length || check[nx][ny])
                    continue;
                dfsFindWords(board, nx, ny, stringBuilder, th.nodes[cur], check);
            }
             if (th.nodes[cur].isEnd) strings.add(stringBuilder.toString());
            stringBuilder.deleteCharAt(stringBuilder.length() - 1);
            check[x][y] = false;
        }
    }
}