题目描述:
思路总结:
我们要设置一个visited,用于记录在当前还正确的路线中该格子是否访问过。
注意:并不是你一个格子访问过就把其设置为访问过,只有当格子访问过且已经纳入当前的正确路线的时候我们才将其visted设置为1。
下面是具体思路:
主要采用了2个技巧:visited访问表和递归的思想。visited表是和board表同样形状的二维表。
1、首先,那么我们继续按照从上到下,从左到右的顺序访问board表,直到遇到了和word单词中第一个字母相等的格子。然后设置这个格子的字母的visited=1.
2、假设我们现在已经找到了word单词的前m个字母的正确格子路线。设置当前到达的第m个格子的visited=1.
3、然后,我们再判断其相邻位置的元素(相邻位置的元素至多4个)是否等于word单词的第m+1个字母。如果4个相邻位置中的元素中一个满足条件的话,那么说明当前仍然属于正确的线路。然后转到第三步。否则,如果,4个相邻的元素都不等于的话,那么说明当前的路线错误,那么撤销步骤2 中被设置为访问过(visited=1)的格子m的visited=1,重新设置为没有访问过visited=0。
4、重复步骤2、3。直到所有board格子都访问结束(表示没有找到正确路线,return false),或者word单词中的所有字母均遍历结束(说明找到正确的路线,return true)。
更多细节见如下代码:
class Solution {
public:
bool check(vector<vector<char>>& board, vector<vector<int>>& visited, int i, int j, string& s, int k){
if(board[i][j]!=s[k]){
return false;
}else if(k == s.length()-1){ //表示字符串已经扫描完
return true;
}
visited[i][j] = true;
vector<pair<int, int>> dirctions{{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
bool result = false;
//分别看上下左右相邻的元素
for(const auto& dir: dirctions){
int newi = i + dir.first, newj = j + dir.second;
if(newi>=0&&newi<board.size()&&newj>=0&&newj<board[0].size()){
if(!visited[newi][newj]){ //如果这个相邻点没有被访问过
//如果没有访问过,就看从这个格子开始能不能构成后面的字符串。
bool flag = check(board, visited, newi, newj, s, k+1);
if(flag){
result = true;
break;
}
}
}
}
//没有纳入正确路线的恢复设置其为没有访问过。
visited[i][j] = false;
return result;
}
bool exist(vector<vector<char>>& board, string word) {
int h = board.size(); // 求得board的行数
int w = board[0].size(); // 求得board的列数
// 初始化一个和board同形的二维数组
vector<vector<int>> visited(h, vector<int>(w));
for(int i = 0; i < h; i++){ //要将每个起点遍历完
for(int j=0; j<w; j++){
bool flag = check(board, visited, i, j, word, 0);
if(flag){
return true;
}
}
}
return false;
}
};