矩阵中的路径
请设计一个函数,用来判断在一个矩阵中是否存在一条路径包含的字符按访问顺序连在一起恰好为给定字符串。
路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。
如果一条路径经过了矩阵中的某一个格子,则之后不能再次进入这个格子。
注意:
- 输入的路径字符串不为空;
- 所有出现的字符均为大写英文字母;
数据范围
矩阵中元素的总个数 [0,900]。
路径字符串的总长度 [1,900]。
样例
c
matrix=
[
["A","B","C","E"],
["S","F","C","S"],
["A","D","E","E"]
]
str="BCCE" , return "true"
str="ASAE" , return "false"
题解
核心思想:深度优先搜索(DFS)结合回溯。
- 起点枚举 :
遍历矩阵中的每一个单元格(i, j)
作为可能的路径起点。 - DFS递归搜索 :
从起点出发,依次匹配字符串的每个字符。具体步骤如下:- 终止条件 :
当前字符与目标字符不匹配,或已匹配完所有字符(u == str.size() - 1
)。 - 路径探索 :
向四个方向(上、右、下、左)扩展路径,并跳过越界或已访问的单元格。 - 回溯恢复现场 :
搜索结束后恢复当前单元格的原始字符,避免影响其他路径的搜索。
- 终止条件 :
时间复杂度分析
- 起点数量 :矩阵共有
m×n
个单元格,其中m
为行数,n
为列数。 - 路径分支 :
每个字符匹配后,最多有 3 个新方向可选(不能走回头路),字符串长度为k
。 - 总时间复杂度 :
O(m×n×3ᵏ) ,其中k
为字符串长度。
cpp
class Solution {
public:
bool hasPath(vector<vector<char>>& matrix, string str) {
// 遍历所有可能的起点
for (int i = 0; i < matrix.size(); i++) {
for (int j = 0; j < matrix[i].size(); j++) {
if (dfs(matrix, str, 0, i, j)) {
return true;
}
}
}
return false;
}
bool dfs(vector<vector<char>>& matrix, string& str, int u, int x, int y) {
// 当前字符不匹配,直接返回false
if (matrix[x][y] != str[u]) return false;
// 已匹配所有字符,返回true
if (u == str.size() - 1) return true;
// 定义四个方向:上、右、下、左
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
// 保存当前字符并标记为已访问
char original = matrix[x][y];
matrix[x][y] = '*'; // 使用特殊字符标记已访问
// 向四个方向递归搜索
for (int i = 0; i < 4; i++) {
int nx = x + dx[i], ny = y + dy[i];
// 检查新坐标是否越界
if (nx >= 0 && nx < matrix.size() && ny >= 0 && ny < matrix[nx].size()) {
if (dfs(matrix, str, u + 1, nx, ny)) {
return true; // 找到路径,提前返回
}
}
}
// 回溯:恢复当前单元格的原始字符
matrix[x][y] = original;
return false;
}
};
代码解释
- 主函数
hasPath
:- 遍历矩阵的每个单元格
(i, j)
,作为DFS的起点。 - 若某一起点出发能找到完整路径,立即返回
true
。
- 遍历矩阵的每个单元格
- 递归函数
dfs
:- 参数说明 :
u
:当前需匹配的字符在字符串中的索引。x, y
:当前搜索的矩阵坐标。
- 字符匹配检查 :
若当前单元格字符与目标字符不匹配,直接返回false
。 - 终止条件 :
若已匹配所有字符(u == str.size() - 1
),返回true
。 - 方向探索 :
使用方向数组生成四个相邻坐标,过滤越界位置后递归搜索。 - 回溯恢复现场 :
将标记为*
的单元格恢复为原字符,确保后续路径搜索不受影响。
- 参数说明 :
关键细节
- 避免重复访问 :
通过临时修改当前单元格为特殊字符*
,确保同一路径中不重复使用单元格。 - 剪枝优化 :
一旦某条路径找到解,立即通过return true
终止后续搜索,减少不必要的递归。