标签:ems 否则 简单 turn 存储 直接 出现 str 不可
给定一个 m x n
二维字符网格 board
和一个字符串单词 word
。如果 word
存在于网格中,返回 true
;否则,返回 false
。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
示例1:
输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"
输出:true
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/word-search
这是一道典型的 DFS + 回溯的题目,在此记录一下 DFS 时的思路。
刚开始刷题时面对 DFS 经常感觉无从下手,后来发现写 DFS 时,不要做太多关于剪枝的考虑,先大刀阔斧地写出 DFS 的框架来,再慢慢优化算法。
DFS 的大方向主要想清楚两件事,一是下一步该去往何方,二是如何判断我是否已经抵达终点。
这两件事在这道题里都十分简单,下一步的方向就是上下左右四个格子,是否已经抵达终点可以通过判断是否已经走到了 word
的最后一位。我们可以轻易地写出如下的代码:
void dfs(int i, int j, int k) {
visited[i][j] = true;
if(k == word.length() - 1) {
visited[i][j] = false;
found = true;
return;
}
for(auto p : directions) {
int ti = i + p[0];
int tj = j + p[1];
if(ti < 0 || ti >= m || tj < 0 || tj >= n || visited[ti][tj] == true)
continue;
if(board[ti][tj] == word[k + 1]) {
dfs(ti, tj, k + 1);
}
}
visited[i][j] = false;
return;
}
接下来是要剪枝,可以看出,虽然在一个方向上找到了结果,但是 DFS 仍然会将所有可能的路线都搜索一遍,这个过程是十分耗时的,因此我们考虑在每次判断要不要向下个方向查找时,都检查一下 found
是否已经为 true
。
原理上我认为这样的剪枝已经够了,但仍然可能出现超时的情况,我们需要将进一步考虑如何加速。比如,首先用哈希表存储所有在 board
中出现的字符,然后判断是否 word
中所有的字符都在 board
中出现过,若某些字符没有在 board
中出现,那是不可能找到的,因此直接返回 false
即可。
class Solution {
private:
vector<vector<int>> directions = {{-1, 0}, {0, -1}, {0, 1}, {1, 0}};
string word;
bool found = false;
int m;
int n;
vector<vector<char>> board;
vector<vector<bool>> visited;
void dfs(int i, int j, int k) {
visited[i][j] = true;
if(k == word.length() - 1) {
visited[i][j] = false;
found = true;
return;
}
for(auto p : directions) {
int ti = i + p[0];
int tj = j + p[1];
if(ti < 0 || ti >= m || tj < 0 || tj >= n || visited[ti][tj] == true)
continue;
if(found)
break;
if(board[ti][tj] == word[k + 1]) {
dfs(ti, tj, k + 1);
}
}
visited[i][j] = false;
return;
}
public:
bool exist(vector<vector<char>>& board, string word) {
this->m = board.size();
this->n = board[0].size();
unordered_set<char> cmap;
for(int i = 0; i < m; i++) {
for(int j = 0; j < n; j++) {
cmap.insert(board[i][j]);
}
}
for(auto c : word) {
if(cmap.find(c) == cmap.end())
return false;
}
this->word = word;
this->board = board;
this->visited.assign(m, vector<bool>(n, false));
for(int i = 0; i < m; i++) {
for(int j = 0; j < n; j++) {
if(board[i][j] == word[0])
dfs(i, j, 0);
if(found)
return true;
}
}
return false;
}
};
标签:ems 否则 简单 turn 存储 直接 出现 str 不可
原文地址:https://www.cnblogs.com/xqmeng/p/14653228.html