- 单词搜索 II
给定一个二维网格 board 和一个字典中的单词列表 words,找出所有同时在二维网格和字典中出现的单词。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。
示例:
输入:
words = [“oath”,“pea”,“eat”,“rain”] and board =
[
[‘o’,‘a’,‘a’,‘n’],
[‘e’,‘t’,‘a’,‘e’],
[‘i’,‘h’,‘k’,‘r’],
[‘i’,‘f’,‘l’,‘v’]
]
输出: [“eat”,“oath”]
刚看到题目想到的解法是暴力求解,试了一下,没想到居然过了。。。
暴力解法就是遍历words数组,将每一个元素挨个在二维网格中查找是否存在。查找方式使用回溯法。需要注意的一点是需要将同一次查找过程中经过的路径做标志,本次查找过后需要复原。
C++代码:
class Solution {
public:
vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
vector<string> vec;
if(words.size()==0||board.size()==0)
return vec;
for(int i=0;i<words.size();i++)
{
if(find(board,words[i]))
vec.push_back(words[i]);
}
return vec;
}
bool find(vector<vector<char>> board,string &str)
{
if(str.size()==0||board.size()==0)
return true;
for(int i=0;i<board.size();i++)
{
for(int j=0;j<board[0].size();j++)
{
if(Iswords(board,i,j,str,0))
{
return true;
}
}
}
return false;
}
bool Iswords(vector<vector<char>>& board,int i,int j,string &str,int k)
{
if(board[i][j]!=str[k])
return false;
if(k==str.size()-1)
return true;
char temp=board[i][j];
board[i][j]='0';
if((i+1<board.size()&&Iswords(board,i+1,j,str,k+1))||
(i-1>=0&&Iswords(board,i-1,j,str,k+1))||
(j+1<board[0].size()&&Iswords(board,i,j+1,str,k+1))||
(j-1>=0&&Iswords(board,i,j-1,str,k+1)))
return true;
board[i][j]=temp;
return false;
}
};
这么做时间复杂度较高。
看到题目提示可以使用前缀树来求解本问题。(若不了解前缀树,可先做leetcode208题)
所以想到首先利用前缀树存储words中所有字符串。从头到尾依次遍历二维网络。遍历过程中使用字符串记录,若字符串不为前缀树的前缀,直接return,继续遍历下一网格点。若前缀树成功查找到字符串,则将字符串添加到返回的数组中,继续遍历本节点,直到遍历完所有网格点。
C++代码为:
class Trail{
public:
bool IsEnd;
Trail* next[26];
Trail(){
IsEnd=false;
for(int i=0;i<26;i++)
{
next[i]=NULL;
}
}
void Insert(string str)
{
Trail* node=this;
for(char ch:str)
{
if(node->next[ch-'a']==NULL)
node->next[ch-'a']=new Trail();
node=node->next[ch-'a'];
}
node->IsEnd=true;
}
bool Search(string str)
{
Trail* node=this;
for(char ch:str)
{
if(node->next[ch-'a']==NULL)
return false;
node=node->next[ch-'a'];
}
return node->IsEnd;
}
bool Ispre(string str)
{
Trail* node=this;
for(char ch:str)
{
if(node->next[ch-'a']==NULL)
return false;
node=node->next[ch-'a'];
}
return true;
}
};
class Solution {
public:
vector<string> vec;
vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
if(words.size()==0||board.size()==0)
return vec;
Trail* trail=new Trail();
for(int i=0;i<words.size();i++)
{
trail->Insert(words[i]);
}
set<string> s;
find(board,trail,s);
return vec;
}
void find(vector<vector<char>> &board,Trail* trail,set<string> &s)
{
if(board.size()==0)
return;
for(int i=0;i<board.size();i++)
{
for(int j=0;j<board[0].size();j++)
{
string str;
Iswords(board,i,j,trail,str,s);
}
}
}
void Iswords(vector<vector<char>>& board,int i,int j,Trail* trail,string str,set<string> &s)
{
if(board[i][j]==' ')
return;
if(!trail->Ispre(str+board[i][j]))
return;
if(trail->Search(str+board[i][j]))
{
if(s.count(str+board[i][j])==0)
{
s.insert(str+board[i][j]);
vec.push_back(str+board[i][j]);
}
}
char temp=board[i][j];
board[i][j]=' ';
if(i+1<board.size())
Iswords(board,i+1,j,trail,str+temp,s);
if(i-1>=0)
Iswords(board,i-1,j,trail,str+temp,s);
if(j+1<board[0].size())
Iswords(board,i,j+1,trail,str+temp,s);
if(j-1>=0)
Iswords(board,i,j-1,trail,str+temp,s);
board[i][j]=temp;
}
};