思路
题中给到的信息:
- 上下左右随便移动,找到字符串路径
- 访问可以重复,但是作为路径不能有重复
方法一:递归深度优先搜索
我们需要判断这个矩阵中的每一个结点是否可以走一条路径,即找到每个结点为起点,后续结点是否可以走出字符串字串的路径,该子问题又可以作为一个递归。因此,可以用图的递归dfs来解决。同时,在走的过程中,要设置一个和矩阵大小相同的bool矩阵表示是否已经访问,如果某个结点访问了,在同一条路线上就不能再访问了,其他路线依旧可以访问,所以若是某条路线不达标,记得将其改回来。
class Solution {
public:
bool dfs(vector<vector<char> >& matrix, int n, int m, int i, int j, string word, int k, vector<vector<bool> >& flag){
if(i < 0 || i >= n || j < 0 || j >= m || (matrix[i][j] != word[k]) || (flag[i][j] == true)){
//下标越界、字符不匹配、已经遍历过不能重复
return false;
}
if(k == word.length() - 1){ //k为记录当前第几个字符
return true;
}
flag[i][j] = true;
if(dfs(matrix, n, m, i - 1, j, word, k + 1, flag)
||dfs(matrix, n, m, i + 1, j, word, k + 1, flag)
||dfs(matrix, n, m, i, j - 1, word, k + 1, flag)
||dfs(matrix, n, m, i , j + 1, word, k + 1, flag))
return true; //该结点任意方向可行就可
flag[i][j] = false; //没找到经过此格的,此格未被占用
return false;
}
bool hasPath(vector<vector<char> >& matrix, string word) {
if(word == "") //优先处理特殊情况
return true;
if(matrix.size() == 0)
return false;
int n = matrix.size();
int m = matrix[0].size();
vector<vector<bool> > flag(n, vector<bool>(m, false)); //初始化flag矩阵记录是否走过
for(int i = 0; i < n; i++){ //遍历矩阵找起点
for(int j = 0; j < m; j++){
if(dfs(matrix, n, m, i, j, word, 0, flag)){
return true;
}
}
}
return false;
}
};
复杂度分析:
- 时间复杂度:O(mn*k^3),其中m与n为矩阵的边长,k为字符串的长度
- 空间复杂度:O(mn),辅助二位数组记录是否走过某节点
方法二:非递归深度优先搜索
具体做法:
像二叉树中序遍历一样,用栈来存储后面可能访问的结点,这里不适用flag数组标记而是直接替换矩阵中的值,当矩阵中的值被替换后代表已经路过,不能再去。回溯的时候也需要用栈记录前一个结点的下标,将替换后的字符再换回去即可回溯。
class Solution {
public:
bool hasPath(vector<vector<char> >& matrix, string word) {
if(word == "") //优先处理特殊情况
return true;
if(matrix.size() == 0)
return false;
int n = matrix.size();
int m = matrix[0].size();
stack<pair<int, int>> s, deepnote; //一个记录深度搜索的结点,一个记录回溯的时候前一个结点
int index = 0; //字符的序列
for(int i = 0; i < n; i++) //遍历每一个结点寻找头结点
for(int j = 0; j < m; j++)
s.push(make_pair(i, j));
while(!s.empty()){
int x=s.top().first;
int y = s.top().second;
if(x < 0 || x > n - 1 || y < 0 || y > m - 1){
s.pop();
}
else if(matrix[x][y] == word[index] && matrix[x][y] != '/'){
if(index == word.size() - 1)
return true;
matrix[x][y]='/'; //将访问过的点标记
index++;
deepnote.push(make_pair(x, y)); //记录前一个结点
s.push(make_pair(x, y + 1)); //将要访问的下一个结点入栈
s.push(make_pair(x, y - 1));
s.push(make_pair(x + 1, y));
s.push(make_pair(x - 1, y));
}else{
if(!deepnote.empty() && deepnote.top() == s.top()){
index--;
matrix[x][y]=word[index]; //回溯
deepnote.pop();
s.pop();
}
else s.pop();
}
}
return false;
}
};
复杂度分析:
- 时间复杂度:O(mn*k^3),其中m与n为矩阵的边长,k为字符串的长度
- 空间复杂度:O(mn),dfs的栈最大是整个矩阵的大小