此题建立在上个问题的基础上:单词搜索–DFS
给定一个二维网格
board
和一个字典中的单词列表words
,找出所有同时在二维网格和字典中出现的单词。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。
你可以假设所有输入都由小写字母 a-z 组成。
C++函数形式:
vector<string> findWords(vector<vector<char>>& board, vector<string>& words)
注:此题来源于Leetcode,详情前往:戳我前往
这个问题是 单词搜索 的升级版,不同在于,这次要求的是找多个字符串。
再使用上次的方法,当然可以解决问题,不过比较暴力,而且时间上可能会超时。
那么我们可以想办法优化一下。
用贪心的思维来想,就是怎样才能减少真正计算的次数呢?
我们发现对于单词ATFWUS
来说,如果ATFWUSMAX
已经存在,那么作为这个单词的前缀,肯定也是存在的,这样我们就可以减少很多不必要的遍历。
所以我们可以使用 前缀树。
于是我们首先想到的就是,遍历一个单词时,可以先去前缀树中查找一下,看是不是已经搜索完毕的前缀,如果是,那么就不必要去搜索。
这是一个很好的思路,但是,实际上,时间的效率不会提高很多,而且空间的消耗还增大了。
因为你仍然需要对每个单词去搜索,如果运气不好,不但没有减少时间,反而因为要记录这些值而加大了空间的消耗。
我们可以换一个角度思考,如果我们事先把每个单词都存入前缀树中,这样,我们只需要从每个结点开始去搜索,在搜索的过程是可以做到所有单词一起搜索了的,这样就可以避免很多不必要的搜索。于是我们的思路是:
isEnd
的值为真时,那么就认为找到了这个单词。并且把isEnd
置为假,目的是防止同一个单词重复检测。我们在结构上需要做的改变是:
str
字段,目的就是方便查询到尾部的时候,直接获取该单词。class Trie {
private:
bool isEnd;
Trie*next[26];
string str;
public:
Trie() {
isEnd=false;
memset(next, 0, sizeof(next));
}
void insert(string word) {
Trie*node=this;
for(char c:word){
if(node->next[c-'a']==NULL){
node->next[c-'a']=new Trie();
}
node=node->next[c-'a'];
}
node->isEnd=true;
node->str=word;
}
void search(vector<string>& result,vector<vector<char>>& board) {
Trie*node=this;
for(int i=0;i<board.size();i++){
for(int j=0;j<board[0].size();j++){
helper(result,board,i,j,node);
}
}
}
void helper(vector<string>& result,vector<vector<char>>& board,int x,int y,Trie*node){
if(node->isEnd==true){
node->isEnd=false;//避免d同样的单词重复寻找
result.push_back(node->str);
return;
}
if(x<0||x==board.size()||y<0||y==board[x].size()) return;
if(board[x][y]=='0'||node->next[board[x][y]-'a']==nullptr) return;
node=node->next[board[x][y]-'a'];
char temp=board[x][y];
board[x][y]='0';
helper(result,board,x+1,y,node);
helper(result,board,x-1,y,node);
helper(result,board,x,y+1,node);
helper(result,board,x,y-1,node);
board[x][y]=temp;
}
};
class Solution {
public:
vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
Trie *root=new Trie();
vector<string>result;
for(auto word:words){
root->insert(word);
}
root->search(result,board);
return result;
}
};
ATFWUS --Writing By 2020–03–22