引言
单词搜索
- 🎈 题目链接:
- 🎈 做题状态:
我的解题
这道题就是dfs深度优先搜索了,找到满足条件的路径。找到起点位置,然后往四个方向进行dfs,并且使用 visited 记录走过的路径。并且 dfs 函数的返回值类型是 bool 类型,在遍历四个方向的时候如果结果为 true 就返回,如果不为true就继续遍历。
为什么这个属于回溯类型里面,因为 visited 数组以及 path路径需要回溯,也就是取消选择。
class Solution {
private:
int direction[4][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
bool dfs(vector<vector<char>>& board, string word, vector<vector<bool>>& visited, string& path, int sX, int sY)
{
if (path == word)
{
return true;
}
int rows = board.size();
int cols = board[0].size();
// 遍历四个方向
for (int i = 0; i < 4; ++i)
{
int nx = sX + direction[i][0];
int ny = sY + direction[i][1];
// 边界情况判断准确
if (nx >= 0 && nx < rows && ny >= 0 && ny < cols && visited[nx][ny] == false && board[nx][ny] == word[path.size()])
{
path.push_back(board[nx][ny]);
visited[nx][ny] = true;
if ( dfs(board, word, visited, path, nx, ny) )
{
return true;
}
path.pop_back();
visited[nx][ny] = false;
}
}
return false;
}
public:
bool exist(vector<vector<char>>& board, string word) {
// 这道题有点像路径搜索了,感觉使用dfs可以查找满足要求的路径。
for (int i = 0; i < board.size(); ++i)
{
for (int j = 0; j < board[0].size(); ++j)
{
if (board[i][j] == word[0])
{
vector<vector<bool>> visited(board.size(), vector<bool>(board[0].size(), false));
string path;
path.push_back(word[0]);
visited[i][j] = true;
if ( dfs(board, word, visited, path, i, j) )
{
return true;
}
}
}
}
return false;
}
};
代码分析
你写的这道 单词搜索(Word Search) 的 DFS 解法已经相当扎实了。整体架构合理、逻辑清晰,回溯控制准确,基本就是一道高质量的标准答案实现。下面我来帮你详细分析你的解题思路、优点、可以优化的地方。
✅ 一、思路概述
你准确抓住了题目的核心:
从矩阵的每一个字符出发,尝试在四个方向上递归寻找下一个字符,直到组成目标字符串或回溯。
你的实现分为以下几个关键步骤:
- 枚举起点
遍历 board
中每个格子,找到所有可能的起点(即字符等于 word[0]
的点)开始 DFS。
- DFS + 回溯搜索路径
从当前点出发,向四个方向递归搜索,只要路径当前拼接的字符串等于 word
,立即返回 true
。
- 剪枝条件
- 越界判断;
- 已访问判断(用
visited
标记); - 当前字符是否匹配下一个目标字符。
- 回溯操作
- 添加字符 → 递归 → 回溯(撤销字符 + 撤销访问状态)。
✅ 二、代码优点
优点 | 描述 |
---|---|
🎯 核心思路准确 | DFS + 回溯的模式完全正确 |
👣 路径构造逻辑清晰 | 用 path 字符串辅助构造路径,直观易懂 |
🔍 剪枝条件完整 | 边界、字符匹配、访问状态都判断到了 |
🔄 回溯恢复彻底 | 使用 visited[nx][ny] = false 和 path.pop_back() |
🔁 多起点尝试 | 使用两层循环穷举起始点,覆盖所有可能路径 |
🧠 三、可以优化的地方(建议改进)
✅ 1. 省略 path
,改用 index
记录搜索进度
你的实现使用了 string path
来构建路径,但其实只需要一个 int index
表示当前匹配到了 word[index]
:
bool dfs(vector<vector<char>>& board, const string& word, vector<vector<bool>>& visited, int x, int y, int index)
{
if (index == word.size()) return true;
// 越界 or 已访问 or 不匹配
int rows = board.size(), cols = board[0].size();
if (x < 0 || x >= rows || y < 0 || y >= cols || visited[x][y] || board[x][y] != word[index])
return false;
visited[x][y] = true;
for (auto& dir : direction) {
if (dfs(board, word, visited, x + dir[0], y + dir[1], index + 1))
return true;
}
visited[x][y] = false;
return false;
}
➡️ 优点:减少字符串构造和比较的开销,提升执行效率。
✅ 2. 提前返回优化:从递归中 return 的地方及时 return
你这块已经写得不错,不过更推荐使用:
if (dfs(...)) return true;
代替
bool found = dfs(...);
if (found) return true;
这可以在大型搜索空间下减少递归深度。
✅ 3. 使用全局方向数组时建议使用 const vector<pair<int,int>>
替代 C 数组
例如:
const vector<pair<int, int>> dirs = {{-1,0}, {1,0}, {0,-1}, {0,1}};
更符合现代 C++ 风格,安全性更高、可读性更好。
✅ 4. 避免重复构造 visited
你在每一个起点都重新构造 visited
,可以提前构造好一个共享变量,然后在每次搜索前清空它(也可接受)。
🔁 四、优化后的示例代码
class Solution {
private:
const vector<pair<int, int>> dirs = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
bool dfs(vector<vector<char>>& board, vector<vector<bool>>& visited,
int x, int y, const string& word, int index)
{
if (index == word.size()) return true;
int rows = board.size(), cols = board[0].size();
if (x < 0 || x >= rows || y < 0 || y >= cols ||
visited[x][y] || board[x][y] != word[index])
return false;
visited[x][y] = true;
for (const auto& [dx, dy] : dirs) {
if (dfs(board, visited, x + dx, y + dy, word, index + 1))
return true;
}
visited[x][y] = false;
return false;
}
public:
bool exist(vector<vector<char>>& board, string word) {
int rows = board.size(), cols = board[0].size();
vector<vector<bool>> visited(rows, vector<bool>(cols, false));
for (int i = 0; i < rows; ++i)
for (int j = 0; j < cols; ++j)
if (board[i][j] == word[0] &&
dfs(board, visited, i, j, word, 0))
return true;
return false;
}
};
✅ 五、总结
项目 | 评价 |
---|---|
算法思路 | ✅ 非常清晰,DFS + 回溯框架到位 |
实现完整性 | ✅ 所有必要的判断和回溯都写到了 |
可优化点 | ✅ 可省略 path,改用 index 表示搜索进度 |
编码风格 | 🔄 可用现代 C++ 替换 C 风格数组,更现代化 |
你这道题已经掌握得很好了,若想提升代码质量与效率,建议考虑采用 index 方案进行优化。