剑指 Offer 12. 矩阵中的路径
个人思路
思路
类似迷宫问题,增加了字符比对
- 递归参数:二维矩阵,字符串,当前坐标x,y(二维矩阵中),当前字符串位置index
- 递归出口:比对到最后一位,x,y越界,字符串不匹配,当前坐标已经被访问过
- 递归体:上下左右移动,递归遍历
注意
- 由于可以从矩阵中的任意一格开始,因此要对整个矩阵遍历做dfs
- 剪枝位置:要么在递归体for循环中,即回溯之前进行,即下次回溯即为满足题目条件的回溯;要么在递归出口位置剪枝,即每次递归时便对参数是否满足题目条件进行判定;对于本题来说,判定条件为,是否在矩阵有效范围内,是否已经被访问过,字符是否相同
二刷
整体来看,思路是比较清晰的,但细节问题处理的不好
思路(和一刷思路不太一样):
- 遍历矩阵
- 找到与word[0]相同的字符进行dfs
- dfs中对该位置的上下左右进行搜索
- 最后如果匹配上整个word,就标记为true,否则为false
细节问题:
- 仍然是dfs中撤销标记的位置问题
- 进入dfs的标记
//进入dfs的条件 if(board[i][j] == word[0]){ //标记当前位置已经访问过,每次运行到该位置,说明矩阵x,y的字符 = word索引字符 dfs(board, word, i, j, 0); vis[i][j] = false; }
- 对上下左右搜索时的标记
//字符相等 且 没有访问过 if(tx >= 0 && ty >= 0 &&tx < board.size() && ty < board[0].size() && board[tx][ty] == word[index + 1] && vis[tx][ty] == false){ vis[tx][ty] = true; dfs(board, word, tx, ty, index + 1); vis[tx][ty] = false; }
- dfs中递归出口的问题
if(flag == true){
return;
}
//比较单词最后一位字符
if(index == word.size() - 1){
if(board[x][y] == word[index]){
flag = true;
}else{
flag = false;
}
return;
}
个人思路代码
错误代码
思路比较乱,没有理清楚具体的递归出口,导致想到什么便写什么,整个代码没有逻辑
class Solution {
public:
bool vis[205][205] = {false};
int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
bool flag;
void dfs(vector<vector<char> >& board, string word, int x, int y, int index){
//递归出口
if(flag == false){
return;
}
//递归体
if(board[x][y] != word[index]){//当前位置不匹配
flag = false;
}
vis[x][y] = true;//标记访问过
//递归出口
if(index == word.size() - 1){//比对到字符串最后一位
if(board[x][y] == word[index] && flag == true){//最后一位相等,且前面均比对成功
flag = true;
}else{//最后一位比对失败
flag = false;
}
return;
}
//递归体
cout << x <<" " << y << " " << flag << endl;
for(int i = 0; i < 4; ++i){
int tx = x + dir[i][0];
int ty = x + dir[i][1];
cout << tx << "&" << ty << endl;
if(tx >= 0 && tx < board.size() && ty >= 0 && ty < board[i].size() && vis[tx][ty] == false&& flag == true && index + 1 < word.size() - 1){
vis[tx][ty] = true;
dfs(board, word, tx, ty, index + 1);
vis[tx][ty] = false;
}
}
}
bool exist(vector<vector<char>>& board, string word) {
for(int i = 0; i < board.size(); ++i){
for(int j = 0; j < board[j].size(); ++j){
flag = true;
cout << "************" << endl;
vis[i][j] = false;
dfs(board, word, i, j, 0);
vis[i][j] = true;
if(flag == true){
break;
}
}
}
return flag;
}
};
正确代码
class Solution {
public:
bool vis[205][205] = {false};
int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
bool flag;
bool dfs(vector<vector<char> >& board, string word, int x, int y, int index){
//递归出口
if(x < 0 || x >= board.size() || y < 0 || y >= board[0].size() || board[x][y] != word[index] || vis[x][y] == true){
return false;
}
if(index == word.size() - 1){
return true;
}
vis[x][y] = true;
//递归体
for(int i = 0; i < 4; ++i){
int tx = x + dir[i][0];
int ty = y + dir[i][1];
// cout << tx << "&" << ty << endl;
if(dfs(board, word, tx, ty, index + 1) == true){
return true;
}
}
vis[x][y] = false;
return false;
}
bool exist(vector<vector<char>>& board, string word) {
for(int i = 0; i < board.size(); ++i){
for(int j = 0; j < board[0].size(); ++j){
if(dfs(board, word, i, j, 0) == true){
return true;
}
}
}
return flag;
}
};
二刷代码
class Solution {
public:
int dir[4][2] = {{1,0}, {-1, 0}, {0, 1}, {0, -1}};
bool vis[205][205];
bool flag = false;
bool exist(vector<vector<char>>& board, string word) {
//遍历矩阵,找到每个word的首字母进行dfs
for(int i = 0; i < board.size(); ++i){
for(int j = 0; j < board[i].size(); ++j){
//判断是否已经找到路径
if(flag == true){
break;
}
//进入dfs的条件
if(board[i][j] == word[0]){
//标记当前位置已经访问过,每次运行到该位置,说明矩阵x,y的字符 = word索引字符
dfs(board, word, i, j, 0);
vis[i][j] = false;
}
}
}
return flag;
}
//x, y 表示矩阵中的位置,index表示word中的索引
void dfs(vector<vector<char> >& board, string word, int x, int y, int index){
if(flag == true){
return;
}
//比较单词最后一位字符
if(index == word.size() - 1){
if(board[x][y] == word[index]){
flag = true;
}else{
flag = false;
}
return;
}
vis[x][y] = true;
for(int i = 0; i < 4; ++i){
int tx = x + dir[i][0];
int ty = y + dir[i][1];
//字符相等 且 没有访问过
if(tx >= 0 && ty >= 0 &&tx < board.size() && ty < board[0].size() && board[tx][ty] == word[index + 1] && vis[tx][ty] == false){
vis[tx][ty] = true;
dfs(board, word, tx, ty, index + 1);
vis[tx][ty] = false;
}
}
}
};