输入:board = [['A','B','C','E'],['S','F','C','S'],['A','D','E','E']], word = "ABCCED"
输出:true
示例 2:
复制代码
输入:board = [['A','B','C','E'],['S','F','C','S'],['A','D','E','E']], word = "SEE"
输出:true
示例 3:
复制代码
输入:board = [['A','B','C','E'],['S','F','C','S'],['A','D','E','E']], word = "ABCB"
输出:false
解题思路:
方法一:回溯 + DFS
核心思路:
从每个格子出发,尝试匹配 word 的第一个字符,然后向四个方向扩展。
匹配成功:继续匹配下一个字符
匹配失败:回溯,换方向
越界或已访问:跳过
关键操作:
标记已访问 :把当前格子改成特殊字符(如 '#'),避免重复使用
四个方向:上、下、左、右
回溯:恢复格子的原字符
具体过程示例:
board = [['A','B','C','E'],['S','F','C','S'],['A','D','E','E']], word = "ABCCED"
复制代码
路径: A → B → C → C → E → D
(0,0) → (0,1) → (0,2) → (1,2) → (2,2) → (2,1)
A B C E
S F C S
A D E E
代码实现:
cpp复制代码
class Solution {
public:
bool exist(vector<vector<char>>& board, string word) {
int m = board.size(), n = board[0].size();
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (dfs(board, word, i, j, 0)) {
return true;
}
}
}
return false;
}
private:
bool dfs(vector<vector<char>>& board, string& word, int i, int j, int index) {
// 匹配完成
if (index == word.size()) return true;
// 越界或不匹配
if (i < 0 || i >= board.size() || j < 0 || j >= board[0].size()
|| board[i][j] != word[index]) {
return false;
}
// 标记已访问
char temp = board[i][j];
board[i][j] = '#';
// 四个方向搜索
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;
}
};
复杂度分析:
设 m × n 是网格大小,L 是单词长度。
维度
复杂度
说明
时间复杂度
O(m × n × 3^L)
每个格子出发,每步最多3个方向(不回头)
空间复杂度
O(L)
递归栈深度
为什么是 3^L 而不是 4^L?
因为每次不能走回头路(已访问的格子被标记),所以每步最多3个方向。
关键细节:
1. 为什么用 '#' 标记已访问?
避免重复使用同一个格子
比额外维护 visited 数组更省空间
回溯时恢复原字符
2. 为什么四个方向用 || 连接?
只要有一个方向能找到,就返回 true。|| 有短路特性,找到后不再继续搜索。
3. 为什么先判断 index == word.size()?
当 index 等于单词长度时,说明所有字符都匹配完了,返回 true。
4. 为什么越界判断放在前面?
避免访问越界的内存,同时判断字符是否匹配。
方法二:用 visited 数组
代码实现:
cpp复制代码
class Solution {
public:
bool exist(vector<vector<char>>& board, string word) {
int m = board.size(), n = board[0].size();
vector<vector<bool>> visited(m, vector<bool>(n, false));
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (dfs(board, word, visited, i, j, 0)) {
return true;
}
}
}
return false;
}
private:
bool dfs(vector<vector<char>>& board, string& word,
vector<vector<bool>>& visited, int i, int j, int index) {
if (index == word.size()) return true;
if (i < 0 || i >= board.size() || j < 0 || j >= board[0].size()
|| visited[i][j] || board[i][j] != word[index]) {
return false;
}
visited[i][j] = true;
bool found = dfs(board, word, visited, i + 1, j, index + 1)
|| dfs(board, word, visited, i - 1, j, index + 1)
|| dfs(board, word, visited, i, j + 1, index + 1)
|| dfs(board, word, visited, i, j - 1, index + 1);
visited[i][j] = false;
return found;
}
};