Leetcode 212. Word Search II

題目:node

Given a 2D board and a list of words from the dictionary, find all
words in the board.

Each word must be constructed from letters of sequentially adjacent
cell, where "adjacent" cells are those horizontally or vertically
neighboring. The same letter cell may not be used more than once in a
word.
Example:數組

Input: words = ["oath","pea","eat","rain"] and board =
[
['o','a','a','n'],
['e','t','a','e'],
['i','h','k','r'],
['i','f','l','v']
]ui

Output: ["eat","oath"] Note: You may assume that all inputs are
consist of lowercase letters a-z.code

這道題是79題word search的follow up,若是按照那道題的作法咱們在二維數組中尋找每個單詞那麼必定會超時,由於每一個單詞都要搜索一次會產生不少重複搜索,因此咱們想到的是從頭至尾遍歷二維數組,在遍歷過程當中dfs,那麼在這個過程當中必定把全部可能組成的單詞都遍歷了一遍,因此咱們想到能夠用一個hashset來存儲須要搜索的單詞,而後在dfs過程當中把每一個產生的單詞在hashset中尋找。
代碼以下:rem

class Solution {
    List<String> res = new ArrayList<>();
    HashSet<String> set = new HashSet<>();
    boolean[][] visited;
    public List<String> findWords(char[][] board, String[] words) {
        visited = new boolean[board.length][board[0].length];
        for (String word : words)   
            set.add(word);
        for (int i = 0; i < board.length; i ++) {
            for (int j = 0; j < board[0].length; j ++) {
                dfs(board, "", i, j);
            }
        }
        return res;
    }
    public void dfs(char[][] board, String cur, int x, int y) {
        if (x == board.length || x < 0 || y == board[0].length || y < 0 || visited[x][y])
            return;
        char c = board[x][y];
        if (set.contains(cur+c)) {
            res.add(cur+c);
            set.remove(cur+c);
        }
        visited[x][y] = true;
        dfs(board, cur+c, x+1, y);
        dfs(board, cur+c, x-1, y);
        dfs(board, cur+c, x, y+1);
        dfs(board, cur+c, x, y-1);
        visited[x][y] = false;
    }
}

但不幸的是這種方法仍是會超時,因此咱們想可否有種方法能讓咱們提早結束backtrack呢,若是在全部單詞中都沒有這個前綴咱們就能夠提早結束backtarcking。所以想到能夠用Trie來實現,代碼以下:input

class Solution {
    class TrieNode {
        TrieNode[] next = new TrieNode[26];
        String word;
        public TrieNode() {}
    }
    TrieNode buildTrie(String[] words) {
        TrieNode root = new TrieNode();
        for (String word : words) {
            TrieNode p = root;
            for (char c : word.toCharArray()) {
                if (p.next[c-'a'] == null)
                    p.next[c-'a'] = new TrieNode();
                p = p.next[c-'a'];
            }
            p.word = word;
        }
        return root;
    }
    List<String> res = new ArrayList<>();
    boolean[][] visited;
    public List<String> findWords(char[][] board, String[] words) {
        visited = new boolean[board.length][board[0].length];
        TrieNode root = buildTrie(words);
        for (int i = 0; i < board.length; i ++) {
            for (int j = 0; j < board[0].length; j ++) {
                if (root.next[board[i][j]-'a'] == null) continue;
                dfs(board, root, i, j);
            }
        }
        return res;
    }
    public void dfs(char[][] board, TrieNode node, int x, int y) {
        if (x == board.length || x < 0 || y == board[0].length || y < 0 || visited[x][y])
            return;
        char c = board[x][y];
        if (node.next[c-'a'] == null)   return;
        if (node.next[c-'a'].word != null) {
            res.add(node.next[c-'a'].word);
            //若是找到了這個單詞就把它設成null,避免重複的結果
            node.next[c-'a'].word = null;
        }
        visited[x][y] = true;
        dfs(board, node.next[c-'a'], x+1, y);
        dfs(board, node.next[c-'a'], x-1, y);
        dfs(board, node.next[c-'a'], x, y+1);
        dfs(board, node.next[c-'a'], x, y-1);
        visited[x][y] = false;
    }
}
相關文章
相關標籤/搜索