经典回溯问题。
选择使用循环+递归的方式进行回溯。
在一个循环内遍历矩阵中的结点,以该点为起点调用寻路函数
在寻路函数中,先判断当前字符串是否满足要求,若是则返回true,否则将其周围四个点拼接至当前字符串尾部,递归调用寻路函数。
为了避免一个字符被多次使用,引入一个visited数组,用于记录被访问过的点。
为了对递归进行剪枝,当当前要拼接的字符与要求的字符串中对应位置的字符不等时,直接返回false。当要访问的结点位置越界时直接返回false。当当前字符串长度大于要求字符串时直接返回false。
这里面在构造visited数组时复习了一下vector的初始化方法。
vector<bool> temp(matrix.at(0).size(),false);
vector<vector<bool>> visited(matrix.size(), temp);
这种vector(x, y)的初始化方法,第一个参数x指定vector的大小,系统会直接为vector分配x*sizeof(T)的空间,即直接在该数组中预建x个元素,当然,之后如果添加新的元素,系统会自动为其分配新的空间,这里不影响vector的动态特性。第二个y指定了这x个元素以什么值进行初始化,比如这个例子中,第一行是将matrix.at(0).size()个元素全部初始化为false,而第二行则是将matrix.size()个元素全部初始化为temp。这种初始化方法虽然不常用,但是用起来还是很方便的。
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param matrix char字符型vector<vector<>>
* @param word string字符串
* @return bool布尔型
*/
bool hasPath(vector<vector<char> >& matrix, string word) {
// write code here
if(!matrix.size() || !matrix.at(0).size()){
return false;
}
vector<bool> temp(matrix.at(0).size(),false);
vector<vector<bool>> visited(matrix.size(), temp);
for(int i = 0;i < matrix.size();i++){
for(int j = 0;j < matrix.at(0).size();j++){
if(findRoad(matrix, visited, word, "", i, j, 0)){
return true;
}
}
}
return false;
}
bool findRoad(vector<vector<char>> mat, vector<vector<bool>>& visited, string word, string str, int row, int col, int len){
if(row < 0 || col < 0 || row > mat.size() - 1 || col > mat.at(0).size() - 1 || visited.at(row).at(col) || len > word.size() - 1 || word[len] != mat.at(row).at(col)){
return false;
}
else{
string temp = str + mat.at(row).at(col);
if(temp == word){
return true;
}
visited.at(row).at(col) = true;
int ur = row - 1;
int lc = col - 1;
int rc = col + 1;
int dr = row + 1;
if(findRoad(mat, visited, word, temp, ur, col, len + 1) || findRoad(mat, visited, word, temp, row, lc, len + 1) || findRoad(mat, visited, word, temp, row, rc, len + 1) || findRoad(mat, visited, word, temp, dr, col, len + 1)){
return true;
}
else{
visited.at(row).at(col) = false;
return false;
}
}
}
};