212. Word Search II

一、题目

  1、审题

  

  2、分析

    给出一个二维字符矩阵 board,一个字符串数组 words。求出矩阵中连续的字符能组成的 words 中的单词,一个单词只能用同一个位置的字符一次。

 

二、解答

  1、思路:

    采用 Trie 字典树。

    ①、根据 words 创建 一个 Trie

    ②、遍历 board,以每个字符为起始字符,在 Trie 中以 DFS 查找是否存在此 word

 1 class Solution {
 2     public List<String> findWords(char[][] board, String[] words) {
 3         List<String> result = new ArrayList<String>();
 4         // 1、构造查找字典
 5         TrieNode root = buildTrie(words);
 6         
 7         // 2、 从每一个字符开始 dfs 查找是否有存在的单词
 8         for (int i = 0; i < board.length; i++) {
 9             for (int j = 0; j < board[0].length; j++) {
10                 dfs(board, i, j, root, result);
11             }
12         }
13         
14         return result;
15     }
16 
17     private void dfs(char[][] board, int i, int j, TrieNode node,
18             List<String> result) {
19         char c = board[i][j];
20         if(c == '#' || node.children[c - 'a'] == null)
21             return;
22         node = node.children[c - 'a'];
23         if(node.word != null) {    // found one
24             result.add(node.word);
25             node.word = null;
26         }
27         
28         board[i][j] = '#';
29         if(i > 0)
30             dfs(board, i - 1, j, node, result);
31         if(j > 0)
32             dfs(board, i, j - 1, node, result);
33         if(i < board.length - 1)
34             dfs(board, i + 1, j, node, result);
35         if(j < board[0].length - 1)
36             dfs(board, i, j + 1, node, result);
37         board[i][j] = c;
38     }
39 
40     private TrieNode buildTrie(String[] words) {
41         TrieNode root = new TrieNode();
42         for(String word: words) {
43             TrieNode node = root;
44             for(char c: word.toCharArray()) {
45                 int i = c - 'a';
46                 if(node.children[i] == null)
47                     node.children[i] = new TrieNode();
48                 node = node.children[i];
49             }
50             node.word = word;
51         }
52         return  root;
53     }
54 }
55 
56 class TrieNode {
57     public boolean isWord;
58     public TrieNode[] children = new TrieNode[26];
59     public String word;
60 
61 }

 

  2、方法二,不使用字典树。采用一个 Boolean 数组记录当前位置是否访问过。

    public List<String> findWords(char[][] board, String[] words) {
        
        int rows = board.length;
        int cols = board[0].length;
        List<String> result = new ArrayList<String>();
        boolean[][] IS_USED = new boolean[rows][cols];

        for(String word: words) {
            for (int row = 0; row < rows; row++) {
                for (int col = 0; col < cols; col++) {
                    char[] cArray = word.toCharArray();
                    if(is_pattered(board, row, col, rows, cols, IS_USED, 0, word.length() - 1, cArray)) 
                        result.add(word);
                }
            }
        }
        
        return new ArrayList<String>(new HashSet<String>(result));
    }

    private boolean is_pattered(char[][] board, int row, int col, int rows, int cols, boolean[][] iS_USED, int start, int end, char[] cArray) {
        
        if(start > end)
            return true;
        
        if(row >= rows || col >= cols || row < 0 || col < 0)
            return false;
        
        if(board[row][col] != cArray[start] || iS_USED[row][col] == true)
            return false;
        
        iS_USED[row][col] = true;
        
        if(is_pattered(board, row + 1, col, rows, cols, iS_USED, start + 1, end, cArray) ||
                is_pattered(board, row - 1, col, rows, cols, iS_USED, start + 1, end, cArray) ||
                is_pattered(board, row, col + 1, rows, cols, iS_USED, start + 1, end, cArray) ||
                is_pattered(board, row, col - 1, rows, cols, iS_USED, start + 1, end, cArray)
        ) {
            iS_USED[row][col] = false;    // 恢复
            return true;
        }
        
        iS_USED[row][col] = false;
        
        return false;
    }

 

posted @ 2018-10-31 21:05  skillking2  阅读(172)  评论(0编辑  收藏  举报