[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.this

For example,
Given words = ["oath","pea","eat","rain"] and board =spa

[
  ['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.code

click to show hint.blog

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

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

 又一道新題,最近LeetCode出現新題的速度略快啊。剛看到題目想到以前有一道Word Search,因此立刻想到暴力搜索每個單詞,可是很不幸跟預想的同樣超時了,看了一下hint,提到了字典樹。因此先用所給的單詞來構建字典樹,而後在dfs搜索字典樹中的單詞,這樣就避免了大量的重複比較。另外若是搜索的路徑已經不是字典樹是的前綴了就能夠直接剪枝返回了。下面是AC代碼。由於要避免重複,我先用了一個set存結果,而後再轉存到result中。get

 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 };

 下面是超時算法:input

 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 };
相關文章
相關標籤/搜索