给定一个二维网格 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 组成。
提示:
你需要优化回溯算法以通过更大数据量的测试。你能否早点停止回溯?
如果当前单词不存在于所有单词的前缀中,则可以立即停止回溯。什么样的数据结构可以有效地执行这样的操作?散列表是否可行?为什么? 前缀树如何?如果你想学习如何实现一个基本的前缀树,请先查看这个问题: 实现Trie(前缀树)。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/word-search-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
提示了使用字典树
可以先将words里的词组成字典树,然后在board里依次找,只要board当前字母是在字典树root下面的分支里,就可以递归的去找
找的过程中,如果中途字典树走不下去了就返回,已经是存在的单词了就添加(但不返回,因为aaa是,aaab可能也是),在四个方向里找,找到可用的就继续递归向下
class Solution {
public:
struct Node {
bool isflag = false;
Node * next[27] = {};
};
setres; //防止结果有重复,多次查到同一个词
vectorans;
Node * root;
vectordirx{ 0,0,1,-1 };
vectordiry{ 1,-1,0,0 };
bool flag;
//组织字典树
void createtree(vector&words) {
root = new Node();
for (auto w : words) {
Node * p = root;
for (int i = 0; i < w.length(); i++) {
if (p->next[w[i] - 'a'] == NULL) {
p->next[w[i] - 'a'] = new Node();
}
p = p->next[w[i] - 'a'];
}
p->isflag = true;
}
}
void backtrack(vector>&board,vector>visited, int row, int col, Node*roott, string cur) {
cur += board[row][col];
roott = roott->next[board[row][col] - 'a'];
if (!roott)return; //找不下去了
if (roott->isflag == true)
{
//ans.push_back(cur);
res.insert(cur);
flag = true;
//return;
}
visited[row][col] = true;
for (int i = 0; i < 4; i++) {
//if (flag == true)
//return;
int nx = row + dirx[i];
int ny = col + diry[i];
if (nx < 0 || ny < 0 || nx >= board.size() || ny >= board[0].size())
continue;
if (visited[nx][ny] == false) {
backtrack(board, visited, nx, ny, roott, cur);
//visited[nx][ny] = false;
//cur.pop_back();
}
}
}
vector findWords(vector>& board, vector& words) {
if (board.size() == 0 || words.size() == 0)
return ans;
createtree(words);
for (int i = 0; i < board.size(); i++) {
for (int j = 0; j < board[i].size(); j++) {
Node * p = root; //每次查看是否符合root下的子分支
flag = false;
if (p->next[board[i][j] - 'a']) {
vector>visited{ board.size(),vector(board[0].size(),false) };
backtrack(board, visited, i, j, p, "");
}
}
}
set::iterator it;
for (it = res.begin(); it != res.end(); it++)
ans.push_back(*it);
return ans;
}
};