关闭

Hard-题目48:212. Word Search II

406人阅读 评论(0) 收藏 举报
分类:

题目原文:
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.
For example,
Given words = [“oath”,”pea”,”eat”,”rain”] and board =

[
  ['o','a','a','n'],
  ['e','t','a','e'],
  ['i','h','k','r'],
  ['i','f','l','v']
]

Return [“eat”,”oath”].
Note:
You may assume that all inputs are consist of lowercase letters a-z.
题目大意:
给出一个由字母组成的二维矩阵,和一串单词,求哪些单词能用矩阵的一条路径表示。
题目分析:
本题是Middle-题目108:79. Word Search的延伸,如果简单的用一个for循环再调用第一题的函数,显然tle没商量。很容易想到是因为前缀相同的单词都进行了重复的搜索。那么针对相同前缀优化想到了什么?没错Trie树!
参考了discuss中一个最快的代码,大致意思是从矩阵的每一个点开始深搜,dfs的搜索路径和Trie树的搜索路径保持一致(即搜索到某一字符串时,当前dfs函数下的trie树节点也要对应一致),如果当前路径在trie树上是空节点,则直接退出;如果找到了一个Trie树节点它是单词,就加入答案并从Trie树上删掉这个单词。这样相同前缀的单词就只搜索了一次。
源码:(language:java)

public class Solution {
    public List<String> findWords(char[][] board, String[] words) {
        List<String> res = new ArrayList<>();
        TrieNode root = buildTrie(words);
        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, TrieNode p, List<String> res) {
        char c = board[i][j];
        if(c == '#' || p.next[c - 'a'] == null) return;
        p = p.next[c - 'a'];
        if(p.word != null) {   // found one
            res.add(p.word);
            p.word = null;     // de-duplicate
        }

        board[i][j] = '#';
        if(i > 0) dfs(board, i - 1, j ,p, res); 
        if(j > 0) dfs(board, i, j - 1, p, res);
        if(i < board.length - 1) dfs(board, i + 1, j, p, res); 
        if(j < board[0].length - 1) dfs(board, i, j + 1, p, res); 
        board[i][j] = c;
    }

    public TrieNode buildTrie(String[] words) {
        TrieNode root = new TrieNode();
        for(String w : words) {
            TrieNode p = root;
            for(char c : w.toCharArray()) {
                int i = c - 'a';
                if(p.next[i] == null) p.next[i] = new TrieNode();
                p = p.next[i];
           }
           p.word = w;
        }
        return root;
    }

    class TrieNode {
        TrieNode[] next = new TrieNode[26];
        String word;
    }
}

成绩:
19ms,91.42%,21ms,4.36%

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:63560次
    • 积分:3275
    • 等级:
    • 排名:第10731名
    • 原创:270篇
    • 转载:53篇
    • 译文:0篇
    • 评论:8条
    文章分类
    最新评论