这道题乍一看基本的思路就是深度优先遍历,如果根据一个词,遍历一遍整个数据表,那复杂度显然是比较高的,每个词都要遍历一遍二维数组表,而且每个字母要做一次深度优先遍历,这种暴力寻找的做法空间没有浪费,但是时间复杂度太高,起初在做这道题的时候,也没有较好的解决办法。但是想到前面有一个题目字典树的做法,通过空间来换取时间上的高效,因此想到这里,就先对原先的字符串数组构建字典树。
题目大意:给定一组字符串数组和一个二维字符数组表,查找二维数组表,而且每个字符串必须由顺序相邻的单元的字母构成,其中“相邻”单元是水平或垂直相邻的单元。 一个单词中不能多次使用相同的字母单元格。
字典序解题思路:
<1>、构建字典树,即将所有字符串拆开用字典树存储起来。
<2>、循环遍历整个二维字符数组,每次采用深度优先遍历,每一次可以将相同开头的字母全部找到。
以下是AC的代码:
struct TrieNode {
vector<TrieNode*> trienodes;
string str;
TrieNode() {
for (int i=0; i<26; ++i) {
trienodes.push_back(NULL);
}
str = "";
}
};
class Trie {
public:
TrieNode* tireroot = new TrieNode();
void insert(string str) {
TrieNode *tmp = tireroot;
for (int i=0; i<str.size(); ++i) {
if (tmp->trienodes[str[i]-'a'] == NULL) {
tmp->trienodes[str[i]-'a'] = new TrieNode();
}
tmp = tmp->trienodes[str[i]-'a'];
}
tmp->str = str;
}
};
class Solution {
public:
vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
if (board.empty() || board[0].size()<1 || words.size()<1) {
return res;
}
vector<vector<bool>> visit(board.size(), vector<bool>(board[0].size(), 0));
Trie T;
for (string str : words) {
T.insert(str);
}
for (int i=0; i<board.size(); ++i) {
for (int j=0; j<board[i].size(); ++j) {
if (T.tireroot->trienodes[board[i][j]-'a']) {
findWords(board, visit, T.tireroot->trienodes[board[i][j]-'a'] , i, j);
}
}
}
return res;
}
void findWords(vector<vector<char>>& board, vector<vector<bool>>&visit, TrieNode* p, int x, int y) {
if (p->str.size() >= 1) {
res.push_back(p->str);
p->str = "";
}
visit[x][y] = 1;
vector<vector<int>> direct = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
for (int i=0; i<direct.size(); ++i) {
int nx = x+direct[i][0], ny = y+direct[i][1];
if (nx>=0&&nx<board.size() && ny>=0&&ny<board[0].size() && !visit[nx][ny] && p->trienodes[board[nx][ny]-'a']) {
findWords(board, visit, p->trienodes[board[nx][ny]-'a'], nx, ny);
}
}
visit[x][y] = 0;
}
private:
vector<string> res;
};