给定一个 m x n 二维字符网格 board 和一个单词(字符串)列表 words,找出所有同时在二维网格和字典中出现的单词。
单词必须按照字母顺序,通过 相邻的单元格 内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。
输入:board = [[“o”,“a”,“a”,“n”],[“e”,“t”,“a”,“e”],[“i”,“h”,“k”,“r”],[“i”,“f”,“l”,“v”]], words = [“oath”,“pea”,“eat”,“rain”]
输出:[“eat”,“oath”]
思路:DFS
对words数组的每一个元素在board中进行DFS回溯搜索即可。
超时
class Solution {
public:
int dx[4] = {-1, 1, 0, 0};
int dy[4] = {0, 0, -1, 1};
bool dfs(vector<vector<char>>& board, string s, int i, int j, int idx)
{
if (idx == s.size()) return true;
int m = board.size(), n = board[0].size();
for (int k = 0; k < 4; ++k) {
int x = i + dx[k];
int y = j + dy[k];
if (x >= 0 && x < m && y >= 0 && y < n && board[x][y] == s[idx]) {
board[x][y] = '0';
if (dfs(board, s, x, y, idx + 1)) {
board[x][y] = s[idx];
return true;
}
board[x][y] = s[idx];
}
}
return false;
}
vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
vector<string> ret;
int m = board.size(), n = board[0].size();
for (string s : words) {
bool find = false;
for (int i = 0; i < m && !find; ++i) {
for (int j = 0; j < n && !find; ++j) {
if (board[i][j] == s[0]) {
board[i][j] = '0';
if (dfs(board, s, i, j, 1)) {
find = true;
ret.emplace_back(s);
}
board[i][j] = s[0];
}
}
}
}
return ret;
}
};
思路二:Trie树 + DFS
struct TrieNode {
vector<TrieNode*> children;
string* word;
TrieNode() : word(nullptr), children(26) {};
~TrieNode() {
for (const auto& child : children)
delete child;
}
};
class Solution {
public:
vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
const int m = board.size(), n = board[0].size();
TrieNode root;
for (auto& word : words) {
TrieNode* p = &root;
for (const auto& c : word) {
if (!p->children[c - 97])
p->children[c - 97] = new TrieNode();
p = p->children[c - 97];
}
p->word = &word;
}
vector<string> ans;
function<void(int, int, int, TrieNode*)> walk = [&](int x, int y, int d, TrieNode* p) {
if (x < 0 || y < 0 || x == n || y == m || !board[y][x])
return;
const char c = board[y][x];
p = p->children[c - 97];
if (!p) return;
if (p->word) {
ans.emplace_back(*p->word);
p->word = nullptr;
}
board[y][x] = 0;
walk(x - 1, y, d + 1, p);
walk(x + 1, y, d + 1, p);
walk(x, y - 1, d + 1, p);
walk(x, y + 1, d + 1, p);
board[y][x] = c;
};
for (int y = 0; y < m; ++y)
for (int x = 0; x < n; ++x)
walk(x, y, 0, &root);
return ans;
}
};