给定一个二维网格 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"]
说明:
你可以假设所有输入都由小写字母 a-z 组成。
字典树+dfs回溯
对字典words构建字典树,之后我们在网格中的每一点作为起点进行深搜回溯。需要注意的一点是,如果单词找到后,需要在字典树中把标记去掉,以防重复搜索。详细过程见代码
struct Node{
bool word;
string str;
unordered_map<char,Node*> next;
};
class Trim{
public:
Node* root;
Trim(){
root = new Node();
}
void insert(string& word){
int len = word.length();
Node* now = root;
for(int i=0; i<len; i++){
if(now->next.count(word[i]) == 0){
Node* node = new Node();
now->next[word[i]] = node;
}
now = now->next[word[i]];
}
now->word = true;
now->str = word;
}
void play(vector<vector<char>>& board,vector<string>& ans){
int m=board.size(),n=board[0].size();
for(int i=0; i<m; i++){ //每个网格作为起点
for(int j=0; j<n; j++){
search(i,j,m,n,root,board,ans);
}
}
}
void search(int i,int j,int m,int n,Node* now,vector<vector<char>>& board,vector<string>& ans){
if(now->word){
now->word = false; //表明该单词已经搜到了
ans.push_back(now->str);
}
if(i<0 || i>m-1 || j<0 || j>n-1) return;
if(now->next.count(board[i][j]) != 0){
char cur = board[i][j];
board[i][j] = '#'; //表明该方格的单词已经被使用过
search(i+1,j,m,n,now->next[cur],board,ans);
search(i-1,j,m,n,now->next[cur],board,ans);
search(i,j+1,m,n,now->next[cur],board,ans);
search(i,j-1,m,n,now->next[cur],board,ans);
board[i][j] = cur; //回溯
}
}
};
class Solution {
public:
vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
Trim trim;
int n = words.size();
for(int i=0; i<n; i++){ //构建字典树
trim.insert(words[i]);
}
vector<string> ans;
trim.play(board,ans);
return ans;
}
};
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/word-search-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。