212. Word Search II

2018-05-16  本文已影响0人  Nancyberry

Description

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']
]

Output:["eat","oath"]

Note:
You may assume that all inputs are consist of lowercase letters a-z.

Hint:

Solution

Trie + DFS, time O((x + m * n) * y), space O(xy)

The time complexity is

很有意思的一道题。想想看在"Word Search"中是怎么做的?遍历board中的每个位置,从它开始,看能不能匹配word。

把思路扩展到这道题上。如果每次只找一个word,总的时间消耗就太大了,而且也没有memo,对于后续的查找没好处。我们应该对一组words进行统一查找,如果遇到一个pos,对应的char不匹配任何一个word,这时候就应该prune了。

所以我们用Trie来表达所有words,然后对于board中的每一个位置,用DFS去匹配Trie。

下面的代码中还有很多巧思,比如:

class Solution {
    public static final int[][] DIRECTIONS = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
    
    public List<String> findWords(char[][] board, String[] words) {
        if (board == null || board.length == 0 || board[0].length == 0
           || words == null || words.length == 0) {
            return Collections.EMPTY_LIST;
        }
        
        Trie root = new Trie();
        for (String word : words) {
            buildTrie(root, word);
        }

        List<String> res = new ArrayList<>();
        for (int i = 0; i < board.length; ++i) {
            for (int j = 0; j < board[0].length; ++j) {
                dfs(board, i, j, root, res);
            }
        }
        return res;
    }
    
    public void dfs(char[][] board, int i, int j, Trie root, List<String> res) {
        if (i < 0 || i >= board.length || j < 0 || j >= board[0].length) {
            return;
        }
        
        char c = board[i][j];
        if (c == '#' || root.children[c - 'a'] == null) {
            return;
        }
        
        board[i][j] = '#';      // mark visited
        root = root.children[c - 'a'];
        if (root.word != null) {
            res.add(root.word);     // found a word
            root.word = null;       // avoid duplicate
        }
        
        for (int[] d : DIRECTIONS) {
            dfs(board, i + d[0], j + d[1], root, res);
        }
        
        board[i][j] = c;    // backtracking
    }
    
    public void buildTrie(Trie root, String word) {
        for (int i = 0; i < word.length(); ++i) {
            int j = word.charAt(i) - 'a';
            if (root.children[j] == null) {
                root.children[j] = new Trie();
            }
            root = root.children[j];
        }
        
        root.word = word;   // set word
    }
    
    class Trie {
        Trie[] children;
        String word;
        
        public Trie() {
            children = new Trie[26];
        }
    }
}
上一篇下一篇

猜你喜欢

热点阅读