题目
分析
这是一个可以用回溯法解决的典型题。
判断是否存在指定的单词,也就是判断是否有一条为对应word的路径
首先在矩阵中任选一个格子作为路径的起点。如果矩阵中的该格子恰好是word中的第i个字符。那么到相邻的格子上寻找路径上的第i+1个字符。除了矩阵边界上的格子,每个都有四个相邻的格子。重复这个过程直到路径上的所有字符都在矩阵中找到相应的位置
由于回溯的递归特性,路径可以看做是一个栈。
当在矩阵中定位好前n个字符的位置之后,如果在第n个字符对应的格子周围都没有找到第(n+1)个单词,这时候在路径上回到第n-1个字符。重新定位第n个字符。
由于路径不能重复进入矩阵的格子,所以如果矩阵上的点是对应的字符,需要把对应的元素标记为已访问。
代码
C++
class Solution {
public:
vector<vector<int>> direction ={{0,1},{0,-1},{1,0},{-1,0}}; # 四个方向
bool exist(vector<vector<char>>& board, string word) {
if(board.size()==0) return false;
if(board[0].size()==0) return false;
int wordIndex = 0; # wordIndex表示word中已经找到的下标
for(int i=0;i<board.size();i++){
for(int j=0;j<board[0].size();j++){
if(board[i][j]==word[wordIndex]){ # 遍历找到word的开始字符
board[i][j]='1'; # 设为1 表示已经访问过该节点
if(ifExist(board,word,wordIndex+1,i,j)) # 回溯判断是否存在路径
return true;
board[i][j]=word[wordIndex]; # 没找到路径 需要回溯 标记重新设为原始值
}
}
}
return false;
}
bool ifExist(vector<vector<char>>& board, string word, int wordIndex,int i,int j){
if(wordIndex==word.size()) return true; # 终止条件 所有字符都已经找到
for(vector<int> dir:direction){ # 遍历4个方向
int iNext = i + dir[0]; # 获取对应的x轴和y轴
int jNext = j + dir[1];
if(iNext<0 || iNext>=board.size()||jNext<0||jNext>=board[0].size()||board[iNext][jNext]=='1'||board[iNext][jNext]!=word[wordIndex])
continue; # 前四个是矩形边界 第5个是该节点已经访问过 第6个是该节点不是对应的字符
board[iNext][jNext]='1'; # 否则该节点是对应的字符 标记已经访问过
if(ifExist(board,word,wordIndex+1,iNext,jNext)) # 对该节点递归调用
return true;
board[iNext][jNext]=word[wordIndex]; # 否则修改标记为原来的字符
}
return false;
}
};