zoukankan      html  css  js  c++  java
  • [LeetCode] Word Search II

    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.

    click to show hint.

    You would need to optimize your backtracking to pass the larger test. Could you stop backtracking earlier?

    If the current candidate does not exist in all words' prefix, you could stop backtracking immediately. What kind of data structure could answer such query efficiently? Does a hash table work? Why or why not? How about a Trie? If you would like to learn how to implement a basic trie, please work on this problem: Implement Trie (Prefix Tree) first.

     又一道新题,最近LeetCode出现新题的速度略快啊。刚看到题目想到之前有一道Word Search,所以马上想到暴力搜索每一个单词,但是很不幸跟预想的一样超时了,看了一下hint,提到了字典树。所以先用所给的单词来构建字典树,然后在dfs搜索字典树中的单词,这样就避免了大量的重复比较。另外如果搜索的路径已经不是字典树是的前缀了就可以直接剪枝返回了。下面是AC代码。因为要避免重复,我先用了一个set存结果,然后再转存到result中。

     1 class Solution {
     2 public:
     3     struct TriNode {
     4         TriNode *ch[26];
     5         bool isWord;
     6         TriNode() : isWord(false) {
     7             for (auto &a : ch) a = NULL;
     8         }
     9     } *root;
    10     
    11     void insert(string word) {
    12         TriNode *p = root;
    13         for (auto &a : word) {
    14             int i = a - 'a';
    15             if (p->ch[i] == NULL) p->ch[i] = new TriNode();
    16             p = p->ch[i];
    17         }
    18         p->isWord = true;
    19     }
    20     
    21     bool isPrefix(string word) {
    22         TriNode *p = root;
    23         for (auto &a : word) {
    24             int i = a - 'a';
    25             if (p->ch[i] == NULL) return false;
    26             p = p->ch[i];
    27         }
    28         return true;
    29     }
    30     
    31     bool isWord(string word) {
    32         TriNode *p = root;
    33         for (auto &a : word) {
    34             int i = a - 'a';
    35             if (p->ch[i] == NULL) return false;
    36             p = p->ch[i];
    37         }
    38         return p->isWord;
    39     }
    40     
    41     Solution() {
    42         root = new TriNode();
    43     }
    44     
    45     bool isValid(vector<vector<char>> &board, vector<vector<bool>> &visit, int x, int y) {
    46         int m = board.size(), n = board[0].size();
    47         if (x < 0 || x >= m || y < 0 || y >= n || visit[x][y]) return false;
    48         return true;
    49     }
    50     
    51     bool dfs(vector<vector<char>> &board, vector<vector<bool>> &visit, set<string> &st, string &s, int x, int y) {
    52         int dx[4] = {1, 0, -1, 0};
    53         int dy[4] = {0, 1, 0, -1};
    54         visit[x][y] = true;
    55         int xx, yy;
    56         for (int i = 0; i < 4; ++i) {
    57             xx = x + dx[i]; yy = y + dy[i];
    58             if (isValid(board, visit, xx, yy)) {
    59                 s.push_back(board[xx][yy]);
    60                 if (isWord(s)) st.insert(s);
    61                 if (isPrefix(s)) dfs(board, visit, st, s, xx, yy);
    62                 s.pop_back();
    63             }
    64         }
    65         visit[x][y] = false;
    66     }
    67     
    68     vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
    69         vector<string> res;
    70         if (board.empty() || board[0].empty() || words.empty()) return res;
    71         for (auto &word : words) insert(word);
    72         int m = board.size(), n = board[0].size();
    73         vector<vector<bool>> visit(m, vector<bool>(n, false));
    74         string s;
    75         set<string> st;
    76         for (int i = 0; i < m; ++i) {
    77             for (int j = 0; j < n; ++j) {
    78                 s.push_back(board[i][j]);
    79                 if (isWord(s)) st.insert(s);
    80                 if (isPrefix(s)) dfs(board, visit, st, s, i, j);
    81                 s.pop_back();
    82             }
    83         }
    84         for (auto &word : st) res.push_back(word);
    85         return res;
    86     }
    87 };

     下面是超时算法:

     1 class Solution {
     2 public:
     3     bool isValid(vector<vector<char>> &board, vector<vector<bool>> &visit, int x, int y) {
     4         int m = board.size(), n = board[0].size();
     5         if (x < 0 || x >= m || y < 0 || y >= n || visit[x][y]) return false;
     6         return true;
     7     }
     8     
     9     bool dfs(vector<vector<char>> &board, vector<vector<bool>> &visit, string word, int idx, int x, int y) {
    10         if (idx == word.length()) return true;
    11         int dx[4] = {1, 0, -1, 0};
    12         int dy[4] = {0, 1, 0, -1};
    13         visit[x][y] = true;
    14         int xx, yy;
    15         for (int i = 0; i < 4; ++i) {
    16             xx = x + dx[i]; yy = y + dy[i];
    17             if (isValid(board, visit, xx, yy) && board[xx][yy] == word[idx] && dfs(board, visit, word, idx + 1, xx, yy)) {
    18                 return true;
    19             }
    20         }
    21         visit[x][y] = false;
    22         return false;
    23     }
    24     
    25     bool exist(vector<vector<char>>& board, string word) {
    26         if (board.empty() || board[0].empty() || word.empty()) return false;
    27         int m = board.size(), n = board[0].size();
    28         vector<vector<bool>> visit(m, vector<bool>(n, false));
    29         for (int i = 0; i < m; ++i) {
    30             for (int j = 0; j < n; ++j) {
    31                 if (board[i][j] == word[0] && dfs(board, visit, word, 1, i, j)) return true;
    32             }
    33         }
    34         return false;
    35     }
    36     
    37     vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
    38         vector<string> res;
    39         if (words.empty()) return res;
    40         sort(words.begin(), words.end());
    41         if (exist(board, words[0])) res.push_back(words[0]);
    42         for (int i = 1; i < words.size(); ++i) {
    43             if (words[i] != words[i-1] && exist(board, words[i])) res.push_back(words[i]);
    44         }
    45         return res;
    46     }
    47 };
  • 相关阅读:
    第六周作业:《人月神话》对我做项目实践的启示(一)
    第五周作业:网站的初步设计
    关于做团队项目时需求分析工作中所学的一部分知识
    软件工程学生的编程能力与编程语言是中文或英文有关系吗?
    面向过程(或者叫结构化)分析方法与面向对象分析方法到底区别在哪里?请根据自己的理解简明扼要的回答。
    当下大部分互联网创业公司为什么都愿意采用增量模型来做开发
    1+X Web前端开发(中级)理论考试样题(附答案)
    1+X Web前端开发(初级)理论考试样题(附答案)
    vi 和vim 的区别
    Linux查看日志三种命令
  • 原文地址:https://www.cnblogs.com/easonliu/p/4514110.html
Copyright © 2011-2022 走看看