class Solution {
public:
bool exist(vector<vector<char>>& board, string &word) {
// 棋盘为空,直接返回 false
if (board.empty()) return false;
// 枚举每一个位置,尝试把它作为单词的起点
for (int i = 0; i < board.size(); i++) {
for (int j = 0; j < board[0].size(); j++) {
// 从 board[i][j] 开始搜索 word[0]
if (dfs(board, word, i, j, 0) == true) {
return true;
}
}
}
// 所有位置都尝试过,仍然找不到
return false;
}
bool dfs(vector<vector<char>>& board, string word,
int i, int j, int index) {
// word 中所有字符都已经匹配完成
// 例如 word 长度为 4,此时 index == 4,说明 0~3 都匹配成功
if (index == word.length()) {
return true;
}
// 当前位置越界,说明这条路走不通
if (i >= board.size() || i < 0 ||
j >= board[0].size() || j < 0) {
return false;
}
// 当前格子的字符不等于当前要匹配的字符
// 说明当前这条路径失败
if (word[index] != board[i][j]) {
return false;
}
// 保存当前字符,后面回溯时需要恢复
char temp = board[i][j];
// 标记当前格子已经使用过
// 防止一条路径中重复使用同一个位置
board[i][j] = '0';
// 当前字符已经匹配成功
// 去上下左右寻找 word[index + 1]
// 四个方向只要有一个成功,found 就是 true
bool found =
dfs(board, word, i + 1, j, index + 1) || // 下
dfs(board, word, i - 1, j, index + 1) || // 上
dfs(board, word, i, j + 1, index + 1) || // 右
dfs(board, word, i, j - 1, index + 1); // 左
// 回溯:恢复当前格子的原字符
// 因为后面其他搜索路径还可能需要使用这个格子
board[i][j] = temp;
// 返回这一条搜索路径最终是否成功
return found;
}
};
你这道题最核心的流程可以记成:
遍历每个格子作为起点
↓
当前字符匹配吗?
↓ ↓
否 是
false 标记已访问
↓
上下左右继续 DFS
↓
恢复原字符
↓
返回结果
尤其是这个 index,你要理解成:
index = 当前正在匹配 word 的第几个字符
例如:
word = "ABC"
index = 0 → 找 A
index = 1 → 找 B
index = 2 → 找 C
index = 3 → 全部找完,return true
还有一个小优化,你这里:
bool dfs(vector<vector<char>>& board, string word, ...)
每次递归都会复制一份 word。更推荐写成:
bool dfs(vector<vector<char>>& board, string& word, ...)
所以建议最终把函数头改成:
bool dfs(vector<vector<char>>& board, string& word,
int i, int j, int index)
这题你可以浓缩成一句话记:
匹配当前字符 → 标记当前格子 → DFS 四个方向找下一个字符 → 恢复当前格子,这就是回溯。