1. 参考题解
作者:liweiwei1419
链接:https://leetcode-cn.com/problems/word-search/solution/zai-er-wei-ping-mian-shang-shi-yong-hui-su-fa-pyth/
2. 这是一个使用回溯算法解决的问题,涉及的知识点有 DFS 和状态重置。
3. 说明:1、偏移量数组在二维平面内是经常使用的,可以把它的设置当做一个技巧,并且在这个问题中,偏移量数组内的 4 个偏移的顺序无关紧要.2. 设置状态数组visited判断该坐标的数值有无使用过,这是一个技巧.
4.先附上自己写的代码,尤其注意vector一定要传入地址,不然内存会爆炸.
class Solution {
public:
int m, n;
bool flag = false;
//方向数组很关键.
int d[4][2] = { { 0,1 },{ 1,0 },{ 0,-1 },{ -1,0 } };
//判断坐标有无越界.
bool legal(int x, int y) {
return x >= 0 && x <= m - 1 && y >= 0 && y <= n - 1;
}
//一定记住传入vector时需要传入他的指针,不然内存会爆炸.
bool backtrace(int i, int j, vector<vector<char>>& board, string word, int index, vector<vector<int>>& state) {
//终止条件,如果到了word的长度,则return.
if (index == word.length() - 1) {
return board[i][j] == word[index];
}
if (board[i][j] == word[index]) {
for (int num = 0; num < 4; num++) {
if (legal(i + d[num][0], j + d[num][1])) {
if (state[i + d[num][0]][j + d[num][1]] == 1)
continue;
state[i + d[num][0]][j + d[num][1]] = 1;
flag = backtrace(i + d[num][0], j + d[num][1], board, word, index + 1, state);
//回溯很重要.
state[i + d[num][0]][j + d[num][1]] = 0;
}
if (flag == true)
break;
}
}
return flag;
}
bool exist(vector<vector<char>>& board, string word) {
//注意边界条件.
if (board.size() <= 0 || board[0].size() <= 0 ||
word.length() > board.size()*board[0].size() || word.length() <= 0)
return false;
m = board.size(); n = board[0].size();
//建立状态数组,指示该数值有无使用过,这是一个技巧.
vector<vector<int>> state(m, vector<int>(n, 0));
//搜索m,n大小的数组.
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
//我传入i,j时已经使用过他,因此需要将它的状态置为1.
state[i][j] = 1;
if (backtrace(i, j, board, word, 0, state))
return true;
//千万记住回溯的时候状态也要回溯,因为state是一个数组.
state[i][j] = 0;
}
}
return false;
}
};
5. 大神的
//大神的
int dir[4][4] = { { -1,0 },{ 1,0 },{ 0,-1 },{ 0,1 } };
bool exist(vector<vector<char>>& board, string word) {
int m = board.size();
int n = board[0].size();
vector<vector<bool>> visited(m, vector<bool>(n));
for (int i = 0; i<m; i++) {
for (int j = 0; j<n; j++) {
if (dfs(i, j, 0, board, word, visited))
return true;
}
}
return false;
}
bool dfs(int x, int y, int index, vector<vector<char>>& board, string &word, vector<vector<bool>>& visited) {
if (index == word.size() - 1) {
return word[index] == board[x][y];
}
if (word[index] == board[x][y]) {
//将当前的点设置为true,比我的简洁。
//我的是将下一个点设置为true,这样还需要单独判断第一个点.
//因此这个是我需要学习的地方.
visited[x][y] = true;
for (int i = 0; i<4; i++) {
int new_x = x + dir[i][0];
int new_y = y + dir[i][1];
//判断下一个点是否可访问.
if (new_x >= 0 && new_x<board.size() && new_y >= 0 && new_y<board[0].size() && !visited[new_x][new_y])
if (dfs(new_x, new_y, index + 1, board, word, visited))
return true;//直接return true.
}
visited[x][y] = false;//回溯
}
return false;
}
final : 标准模板
class Solution {
public:
bool dfs(vector<vector<char>>& board, string word, int index, int i, int j) {
if(index==word.length()) return true;
if(i<0 || i>=board.size() || j<0 || j>=board[0].size()) return false;
if(board[i][j]=='#') return false;
if(board[i][j]!=word[index]) return false;
index++;
char tmp = board[i][j];
board[i][j] = '#';
bool res = dfs(board,word,index,i+1,j) || dfs(board,word,index,i-1,j) ||
dfs(board,word,index,i,j-1) || dfs(board,word,index,i,j+1);
board[i][j] = tmp;
index--;
return res;
}
bool exist(vector<vector<char>>& board, string word) {
int m = board.size(), n = board[0].size();
if(m==0 || n==0) return false;
if(word.length()==0) return false;
for(int i=0;i<m;i++) {
for(int j=0;j<n;j++) {
if(dfs(board,word,0,i,j)) return true;
}
}
return false;
}
};