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
.
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.
这道题是在字母表中找多个单词,题目难度为Hard。
题目和第79题(传送门)相关,第79题找一个单词,通过回溯法能够轻松解决题目,在处理79题时用了isUsed数组来标记每个位置是否已经遍历到,其实是没必要的。具体回溯法的思路就不解释了,相信大家都清楚。
这里要找多个单词,逐个通过回溯法查找效率肯定很低,就不考虑了。题目提示用字典树,解决起来就很方便了,第208题(传送门)是设计字典树的题目,不清楚字典树的同学可以先看下。遍历到某个位置时,之前遍历位置组成的字符串如果不是任何待查找字符串的前缀,就可以结束当前递归的分支了。是否是前缀可以通过遍历位置字典树节点指针是否为空来判断,如果为空,表明没有待查找字符串以此为前缀,结束分支,如果不为空可继续深度优先遍历。具体代码:
class TrieNode {
public:
vector child;
bool isIn;
// Initialize your data structure here.
TrieNode() : child(vector(26, NULL)), isIn(false) {}
};
class Trie {
public:
Trie() : root(new TrieNode()) {}
~Trie() {
delNode(root);
}
void delNode(TrieNode* n) {
for(int i=0; i<26; ++i) {
if(n->child[i]) delNode(n->child[i]);
}
delete n;
}
TrieNode* getRoot() {
return root;
}
// Inserts a word into the trie.
void insert(string word) {
TrieNode* n = root;
for(auto ch:word) {
if(n->child[ch-'a'] == NULL)
n->child[ch-'a'] = new TrieNode();
n = n->child[ch-'a'];
}
n->isIn = true;
}
private:
TrieNode* root;
};
class Solution {
void chkExist(vector>& board, TrieNode* n, vector& ret, string curStr, int r, int c) {
n = n->child[board[r][c]-'a'];
if(n) {
curStr += board[r][c];
if(n->isIn) {
ret.push_back(curStr);
n->isIn = false;
}
char ch = board[r][c];
board[r][c] = 0;
if(r > 0 && board[r-1][c])
chkExist(board, n, ret, curStr, r-1, c);
if(r < board.size()-1 && board[r+1][c])
chkExist(board, n, ret, curStr, r+1, c);
if(c > 0 && board[r][c-1])
chkExist(board, n, ret, curStr, r, c-1);
if(c < board[0].size()-1 && board[r][c+1])
chkExist(board, n, ret, curStr, r, c+1);
board[r][c] = ch;
}
}
public:
vector findWords(vector>& board, vector& words) {
vector ret;
int row = board.size();
if(!row) return ret;
int col = board[0].size();
if(!col) return ret;
Trie t;
for(auto s:words) t.insert(s);
for(int i=0; i|