October 14, 2019

212. Word Search II

212. Word Search II

General idea: backtracking (dfs).

Sol 1. DFS [TLE]

Use DFS to find each word in the board -> 每个单词都要进行一遍dfs
参考 79. Word Search, 一样的解法
Time complexity: O(sum(m * n * 4^l)), board size is m * n, word max length is l. For every word, time is O(m * n * 4^l). Total time complexity for all words is the sum of all time complexities for every word. Space complexity: O(l)

class Solution {
    public List<String> findWords(char[][] board, String[] words) {
        List<String> res = new ArrayList<>();
        if (board.length == 0 || board[0].length == 0) {
            return res;
        }
        for (String word : words) {
            if (exist(board, word)) {
                res.add(word);
            }
        }
        return res;
    }
    
    private boolean exist(char[][] board, String word) {
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[0].length; j++) {
                if (search (i, j, 0, board, word)) {
                    return true;
                }
            }
        }
        return false;
    }
    
    private boolean search(int i, int j, int index, char[][] board, String word) {
        if (index == word.length()) {
            return true;
        }
        if (i < 0 || j < 0 || i > board.length - 1 || j > board[0].length - 1) { // 剪枝
            return false;
        }
        if (board[i][j] != word.charAt(index)) { // 剪枝
            return false;
        }
        char cur = board[i][j];
        board[i][j] = '#';
        boolean found = search(i - 1, j, index + 1, board, word) 
            || search(i + 1, j, index + 1, board, word)
            || search(i, j - 1, index + 1, board, word)
            || search(i, j + 1, index + 1, board, word);
        board[i][j] = cur;
        return found;
    }
}

Sol 2. DFS + Trie

Build a trie of the dictionary and use DFS to traverse the board, the path must also exist in trie.
用trie记录word路径,不需要每个单词都做一遍backtracking。如果有前缀相同的单词,优势明显。
参考这个帖子, 不是空间最优解,但是比较好理解。
Trie 的实现见 208. Implement Trie (Prefix Tree)
Time complexity: O(m * n * 4^l)
Space complexity: O(sum(l)), the total length of all the words

class Solution {
    public List<String> findWords(char[][] board, String[] words) {
        Set<String> res = new HashSet<>(); // 注意去重
        if (board == null || board.length == 0 || board[0].length == 0 || words == null || words.length == 0) {
            return new ArrayList<>(res);
        }
        
        Trie trie = new Trie();
        for (String word : words) {
            trie.insert(word);
        }
        
        boolean[][] visited = new boolean[board.length][board[0].length];
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[0].length; j++) {
                search (i, j, "", trie, board, visited, res);
            }
        }
        return new ArrayList<>(res);
    }
    
    private void search(int i, int j, String s, Trie trie, char[][] board, boolean[][] visited, Set<String> res) {
        if (i < 0 || j < 0 || i > board.length - 1 || j > board[0].length - 1 || visited[i][j]) {
            return;
        }
        s += board[i][j];
        
        if (!trie.startsWith(s)) {
            return;
        }
        if (trie.search(s)) {
            res.add(s);
        }
        visited[i][j] = true;
        search(i - 1, j, s, trie, board, visited, res);
        search(i + 1, j, s, trie, board, visited, res);
        search(i, j - 1, s, trie, board, visited, res);
        search(i, j + 1, s, trie, board, visited, res);
        visited[i][j] = false;
    }
}
comments powered by Disqus